I am writing a script in bash on Linux and need to go through all subdirectory names in a given directory. How can I loop through these directories (and skip regular files)?
For example:
the given directory is /tmp/
it has the following subdirectories: /tmp/A, /tmp/B, /tmp/C
I want to retrieve A, B, C.
If you want to execute multiple commands in a for loop, you can save the result of
find
withmapfile
(bash >= 4) as an variable and go through the array with${dirlist[@]}
. It also works with directories containing spaces.The
find
command is based on the answer by Boldewyn. Further information about thefind
command can be found there.A short explanation:
find
finds files (quite obviously). is the current directory, after the cd it's
/tmp
(IMHO this is more flexible than having/tmp
directly in the find command. You have only one place, thecd
, to change, if you want more actions to take place in this folder)-maxdepth 1
and-mindepth 1
make sure, thatfind
really, only looks in the current dir and doesn't include '.
' in the result-type d
looks only for directories-printf '%f\n
prints only the found folder's name (plus a newline) for each hit.E voila!
You can loop through all directories including hidden directrories (beginning with a dot) with:
note: using the list
*/ .*/
works in zsh only if there exist at least one hidden directory in the folder. In bash it will show also.
and..
Another possibility for bash to include hidden directories would be to use:
If you want to exclude symlinks:
To output only the trailing directory name (A,B,C as questioned) in each solution use this within the loops:
Example (this also works with directories which contains spaces):
find . -type d -maxdepth 1
The technique I use most often is
find | xargs
. For example, if you want to make every file in this directory and all of its subdirectories world-readable, you can do:The
-print0
option terminates with a NULL character instead of a space. The-0
option splits its input the same way. So this is the combination to use on files with spaces.You can picture this chain of commands as taking every line output by
find
and sticking it on the end of achmod
command.If the command you want to run as its argument in the middle instead of on the end, you have to be a bit creative. For instance, I needed to change into every subdirectory and run the command
latemk -c
. So I used (from Wikipedia):This has the effect of
for dir $(subdirs); do stuff; done
, but is safe for directories with spaces in their names. Also, the separate calls tostuff
are made in the same shell, which is why in my command we have to return back to the current directory withpopd
.