web-dev-qa-db-fra.com

cd dans tous les répertoires, exécutez la commande sur les fichiers de ce répertoire et retournez au répertoire courant précédent

J'essaie d'écrire un script qui sera exécuté dans un répertoire donné avec de nombreux sous-répertoires de niveau unique. Le script sera cd dans chacun des sous-répertoires, exécutera une commande sur les fichiers du répertoire et sortira cd pour continuer dans le répertoire suivant. Quelle est la meilleure façon de procéder?

44
Something Jones
for d in ./*/ ; do (cd "$d" && somecommand); done
96
psusi

La meilleure façon est de ne pas utiliser du tout cd:

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

execdir est comme exec, mais le répertoire de travail est différent:

-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.

Ce n'est pas POSIX.

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

La commande ci-dessus n'a pas besoin de faire de sous-shell - elle suit simplement sa progression dans le Shell actuel en alternant $OLDPWD et $PWD. Quand vous cd - le Shell échange la valeur de ces deux variables, essentiellement, car il change de répertoire. Il imprime également le nom de chaque répertoire car il y fonctionne sur stderr.

Je viens juste d'y jeter un deuxième coup d'œil et j'ai décidé que je pouvais faire mieux avec la gestion des erreurs. Il sautera un répertoire dans lequel il ne peut pas cd - et cd affichera un message expliquant pourquoi stderr - et il break avec un code de sortie différent de zéro si votre command ne s'exécute pas correctement ou si vous exécutez command affecte en quelque sorte sa capacité à retourner dans votre répertoire d'origine - $OLDPWD. Dans ce cas, il fait également un cd - last - et écrit le nom du répertoire de travail actuel résultant dans stderr.

2
mikeserv
pushd subdir
# do stuff
popd

pushd/popd sont des commandes bash qui fournissent une pile de répertoires. Vous pouvez faire plusieurs pushds puis plusieurs popds et revenir là où vous avez commencé. Vous pouvez également manipuler la pile avec dirs.

En tant que commande bash intégrée, la documentation se trouve dans la page de manuel bash (man 1 bash et recherchez (/) pour pushd, n pour avancer dans les résultats de la recherche) ou utilisez help pushdhelp popdhelp dirs.

2
drewbenn
for D in ./*; do
    if [ -d "$D" ]; then
        cd "$D"
        run_something
        cd ..
    fi
done
1
Kirill