cd into all directories, execute command on files in that directory, and return to previous current directory

for d in ./*/ ; do (cd "$d" && somecommand); done

The best way is to not use cd at all:

find some/dir -type f -execdir somecommand {} \;

execdir is like exec, but the working directory is different:

-execdir command {} [;|+]
  Like   -exec,   but  the  specified  command  is  run  from  the
  subdirectory containing the matched file, which is not  normally
  the  directory  in  which  you  started  find.  This a much more
  secure  method  for  invoking  commands,  as  it   avoids   race
  conditions  during resolution of the paths to the matched files.

It is not POSIX.


cd -P .
for dir in ./*/
do cd -P "$dir" ||continue
   printf %s\\n "$PWD" >&2
   command && cd "$OLDPWD" || 
! break; done || ! cd - >&2

The above command doesn't need to do any subshells - it just tracks its progress in the current shell by alternating $OLDPWD and $PWD. When you cd - the shell exchanges the value of these two variables, basically, as it changes directories. It also prints the name for each directory as it works there to stderr.

I just had a second look at it and decided I could do a better job with error handling. It will skip a dir into which it cannot cd - and cd will print a message about why to stderr - and it will break w/ a non-zero exit code if your command does not execute successfully or if running command somehow affects its ability to return to your original directory - $OLDPWD. In that case it also does a cd - last - and writes the resulting current working directory name to stderr.

Tags:

Shell Script