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. |
$ help while
And $1 may not be set. if [ ! $1 ]; then fi |
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?
|
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? |
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.
|
I just realized that I had mixed a couple of things up. I don't need the sticky bit. just the setuid.
|
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. |
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 . Now if we wanted to look at all the items inside the '.' directory, we would need something like: Code:
for file in $1/* 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) |
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!
|
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. |
@Shadow_7 - The below is invalid information based on the interpreter already having been set inside the script:
Quote:
Also, without a glob, your for loop will also not function as expected. |
Quote:
$ 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. |
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. |
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. |
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. |