Traverse all subdirectories in and do something in Unix shell script

I want my shell script to visit all subdirectories in a main directory. Do something in directories, sent output to a spool file and move on to next directory.
Main Dir = /tmp
Sub Dir = A B C D (Four sub directories)

Asked By: Ashish


I am a complete bash newbie, but a UN*X veteran. Although doubtless this can be done in Bash shell scripting, in the old days we used find [-maxdepth <levels>] <start-dir> -exec <command> ; to achieve this. You could do a man find and play around, perhaps until someone tells you how to do it in bash!

Answered By: JonBrave

Use a for loop:

for d in $(find /path/to/dir -maxdepth 1 -type d)
  #Do something, the directory is accessible with $d:
  echo $d
done >output_file

It searches only the subdirectories of the directory /path/to/dir. Note that the simple example above will fail if the directory names contain whitespace or special characters. A safer approach is:

find /tmp -maxdepth 1 -type d -print0 |
  while IFS= read -rd '' dir; do echo "$dir"; done

Or in plain bash:

for d in /path/to/dir/*; do
  if [ -d "$d" ]; then
    echo "$d"

(note that contrary to find that one also considers symlinks to directories and excludes hidden ones)

Answered By: chaos

I got the solution. The find command below meets my requirements.

find . -maxdepth 1 -type d ( ! -name . ) -exec bash -c "cd '{}' && ls -l |awk '{ print $9 }' |grep `date +"%m%d%Y"`|xargs echo" ;
Answered By: Ashish

Looks like you want the filenames under each of the subdirs; the ls -l | awk is not robust enough, for what if those filenames comprise whitespace and/or newlines? The below find would work even for finds that donot happen to have the -maxdepth going for them:

find . ! -name . -type d -prune -exec sh -c '
   cd "$1" && 
   find "." ! -name . -prune  -type f
' {} {} ;
Answered By: user218374

It’s also possible using ls, grep, and tr

for dir in $(ls -1FA | grep / | tr -d /); do echo $dir/something; done

ls -1FA | grep / | tr -d / | while IFS= read -r TD; do echo $TD/something; done

du/sed can also be used as a selector if your ls lacks the above options

du --max-depth=1 | sed -e 's/^.*.///' | grep -v '.$'

It may be important to note these examples return hidden directories and exclude parent and current directories

Answered By: JGurtz
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.