LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Help with a recursive bash script (https://www.linuxquestions.org/questions/linux-newbie-8/help-with-a-recursive-bash-script-4175496920/)

yimmy1890 03-03-2014 06:27 PM

Help with a recursive bash script
 
I am in the only Linux class offered at my school, and there is an assignment that is driving me nuts. I have to create a bash script that has a function that can be called recursively to scan the directory specified in the first argument, and list the any file with the setuid in ls -l format. If another directory is found the script should recall itself with the new path.

I thought that I had an idea of how to it using a for loop with if statements to test the directory for the stick bits and the sub-directories, but I cannot even get the function to list the file that I created with the sticky bit. I know this is way wrong, but this is how i started my script just to test for the sticky bit.

#!/bin/bash

setuid(){

for file in $1; do

if [ -u $file ]; then

ls -l $file
fi

done
}

setuid $1

Like I said, this is terrible and I have a feeling that I do not know what I'm actually doing. I am a super noob, and any help is appreciated.

Shadow_7 03-03-2014 06:30 PM

$ help while

And $1 may not be set.

if [ ! $1 ]; then
fi

yimmy1890 03-03-2014 06:36 PM

Thanks for the quick response. I didn't set $1 just in this example, but have tried the directory that I created the file in and I cannot get i to work. You think that I should use a while loop instead?

grail 03-03-2014 08:29 PM

Please tell us what is the value of $1?

Also, currently this has no sign of recursiveness ... is this coming after you solve this part?

---------- Post added 04-03-14 at 10:29 ----------

Please tell us what is the value of $1?

Also, currently this has no sign of recursiveness ... is this coming after you solve this part?

yimmy1890 03-03-2014 08:43 PM

The value of $1 will be a directory or "." if no argument is specified. You are correct the I haven't got ti the recursion yet. However, if you have any tips on making it recall itself when a directory is encountered and the new directory path included in the argument it would be greatly appreciated.

yimmy1890 03-03-2014 08:49 PM

I just realized that I had mixed a couple of things up. I don't need the sticky bit. just the setuid.

yimmy1890 03-03-2014 08:56 PM

I know it said not to do this in the rules, but maybe I am not explaining what I need to do very well. Here is the full problem.

Write out a bash script called 'b.sh' that has a function that can be called recursively to scan the directory specified by it's first argument ($1) for any file that is setuid and print out that file in ls -l format. For any directory it encounters the function should call itself with the new computed path. This function should be called initially with the first argument supplied to the script or "." if no argument is supplied to the script.

grail 03-03-2014 09:37 PM

So let us step back a little for a sec. If you supply something like '.', your for loop will look like:
Code:

for file in .
do
  ...
done

So this will run the contents of the for loop for exactly 1 iteration using '.' as the only thing to be tested.

Now if we wanted to look at all the items inside the '.' directory, we would need something like:
Code:

for file in $1/*
do
  ...
done

Now the glob will expand to all items, files and directories, within that top directory.

As for the recursion, firstly you need to remember to test what type of item you are looking at, ie so that once a directory is found you can recall your function.
Another thing to remember, scope of variables will play a part (if you are not careful)

yimmy1890 03-03-2014 10:15 PM

Thank you, grail. That gets me started in the right direction. Its getting kind of late here, so I will have to continue with this in the morning. Any other tips you might think of that can help me along the way would be greatly appreciated. I will post back on here tomorrow if I am still stuck. Thanks!

Shadow_7 03-03-2014 11:02 PM

so....

if [ ! $1 ]; then
FIRST_PARM="."
else
FIRST_PARM="$1"
fi

for FILE in $FIRST_PARM .....etc.....

If you check $1 and it has not been passed, then your script will fail. Where $1 is the first parameter. And $0 is the name of the script. Also bear in mind that some distros like debian default to dash. Even if you set your shell to bash, when you launch a script with sh or ./ it will run under dash. Unless you run it "bash script.sh". It probably wont affect your low level thing, but some bash extras do not function under dash. Like ${VAR:1:1} to parse parts of strings.

grail 03-03-2014 11:27 PM

@Shadow_7 - The below is invalid information based on the interpreter already having been set inside the script:
Quote:

Even if you set your shell to bash, when you launch a script with sh or ./ it will run under dash. Unless you run it "bash script.sh".
By defining the interpreter at the start of the script, once executed it will use that interpreter (in this case the bash shell) to process the data inside the script.

Also, without a glob, your for loop will also not function as expected.

Shadow_7 03-04-2014 07:49 AM

Quote:

Originally Posted by grail (Post 5128486)
@Shadow_7 - The below is invalid information based on the interpreter already having been set inside the script:

By defining the interpreter at the start of the script, once executed it will use that interpreter (in this case the bash shell) to process the data inside the script.

Also, without a glob, your for loop will also not function as expected.

It depends on the distro and the day of the week I guess. For me:

$ export TEMP=ABCDEF; export TEMP2=${TEMP:2:2}; echo $TEMP "-" $TEMP2

would work on CLI, but not in a script. In debian sid if launched with sh or ./ it fails via Bad substitution (as it would in dash), even with the #! /bin/bash as the header. But if launched with bash it executes as expected. If done on the cli in bash it works. If done on the cli in dash (debians default) it fails. For all intents the interpreter line at the top of the script is ignored (in debian). In theory it shouldn't be, but in practice it appears to be.

grail 03-04-2014 08:39 AM

Well I will have to believe you as I am not familiar with Debian, although it does seem to fly in the face of any other distribution I have used and the whole point of defining an interpreter.

Out of curiosity, what if the interpreter is perl or python, does it ignore these too?

I am not sure why you use export in your example either, is there a reason you cannot simply assign the values?
I mean your example makes sense as it is on the cli, hence subject to whichever shell you are in.

Shadow_7 03-04-2014 01:09 PM

If I add the +x permission and use ./ it uses the interpreter line. Otherwise sh uses dash and bash uses bash, regardless of what the interpreter line says. And ./ wont run at all without the +x permission.

I can use just the var name in script, and I guess it works on the cli for the example without the export. But doesn't work if you're wanting something like LANG set and passed when you chroot using a one liner.

jpollard 03-04-2014 02:43 PM

When processing directories recursively, watch out for running out of parameters on large directories.

This is what the find command does quite well.

I realize this is a homework problem and the directory tree will almost certainly be limited in depth and width.


All times are GMT -5. The time now is 10:53 PM.