tags:

views:

94

answers:

5

I am working on a script that needs to perform an action in every sub-directory of a specific folder.

What is the most efficient way to write that?

+4  A: 

find . -type d -print0 | xargs -0 -n 1 my_command

Paul Tomblin
can I feed the return value of that find into a for loop? This is part of a larger script...
Mike Williamson
@Mike, unlikely. $? will probably get you the status of the find or the xargs command, rather than `my_command`.
Paul Tomblin
+2  A: 
for D in `find . -type d`
do
    //Do whatever you need with D
done
Mike Clark
+1, I think this is cleaner. I use this kind of construct all the time xD I fire up a terminal, write that with semicolons so it fits a line, and do whatever I need to do.
Santiago Lezica
I agree. So clean I can almost pretend its Ruby. Thanks Everybody! :)
Mike Williamson
this will break on white spaces
ghostdog74
Also, note you need to tweak the `find` params if you want recursive or non-recursive behavior.
Chris
+4  A: 

A version that avoids creating a sub-process:

for D in *; do
    if [ -d "${D}"]; do
        echo "${D}"   # your processing here
    fi
done

Or if your command is a single command this is more concise:

for D in *; do [ -d "${D}"] && my_command; done

Or an even more concise version (thanks @enzotib). Note that in this version each value of D will have a trailing slash:

for D in */; do my_command; done
kanaka
You can avoid the `if` or `[` with: `for D in */; do`
enzotib
+1  A: 

the accepted answer will break on white spaces if the directory names have them, and the preferred syntax is $() for bash/ksh. Use GNU find -exec option with +; eg

find .... -exec mycommand +; #this is same as passing to xargs

or use a while loop

find .... |  while read -r D
do
  ...
done 
ghostdog74
+2  A: 

This will create a subshell (which means that variable values will be lost when the while loop exits):

find . -type d | while read -r dir
do
    something
done

This won't:

while read -r dir
do
    something
done < <(find . -type d)

Either one will work if there are spaces in directory names.

Dennis Williamson
For even better handling of weird filenames (including names that end with whitespace and/or include linefeeds), use `find ... -print0` and `while IFS="" read -r -d $'\000' dir`
Gordon Davisson
@Gordon: `-d ''` works just as well as the octal null.
Dennis Williamson