231 votes

Comment aller dans chaque répertoire et exécuter une commande ?

Comment puis-je écrire un bash script qui passe par chaque répertoire à l'intérieur d'un parent_directory et exécute a commande en chaque répertoire .

La structure des répertoires est la suivante :

parent_directory (le nom peut être n'importe quoi - il ne suit pas un modèle)

  • 001 (les noms des répertoires suivent ce modèle)
    • 0001.txt (les noms de fichiers suivent ce modèle)
    • 0002.txt
    • 0003.txt
  • 002
    • 0001.txt
    • 0002.txt
    • 0003.txt
    • 0004.txt
  • 003
    • 0001.txt

le nombre de répertoires est inconnu.

255voto

Christian Vielma Points 1313

Este réponse posté par Todd m'a aidé.

find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && pwd" \;

El \( ! -name . \) évite d'exécuter la commande dans le répertoire courant.

135voto

Mark Longair Points 93104

Vous pouvez faire ce qui suit, lorsque votre répertoire courant est parent_directory :

for d in [0-9][0-9][0-9]
do
    ( cd "$d" && your-command-here )
done

El ( y ) créer un sous-shell, afin que le répertoire courant ne soit pas modifié dans le script principal.

74voto

Piyush Singh Points 1871

Pour ce faire, il suffit d'ajouter le piping et d'utiliser ensuite xargs . Le problème est que vous devez utiliser le -I qui remplacera la sous-chaîne de votre commande bash par la sous-chaîne transmise par chacun des paramètres suivants xargs .

ls -d */ | xargs -I {} bash -c "cd '{}' && pwd"

Vous pouvez remplacer pwd avec la commande que vous voulez exécuter dans chaque répertoire.

64voto

kenorb Points 2464

Si vous utilisez GNU find vous pouvez essayer -execdir paramètre, par exemple :

find . -type d -execdir realpath "{}" ';'

ou (selon Commentaire de @gniourf_gniourf ):

find . -type d -execdir sh -c 'printf "%s/%s\n" "$PWD" "$0"' {} \;

Remarque : vous pouvez utiliser ${0#./} au lieu de $0 pour fixer ./ à l'avant.

ou un exemple plus pratique :

find . -name .git -type d -execdir git pull -v ';'

Si vous voulez inclure le répertoire courant, c'est encore plus simple en utilisant -exec :

find . -type d -exec sh -c 'cd -P -- "{}" && pwd -P' \;

ou en utilisant xargs :

find . -type d -print0 | xargs -0 -L1 sh -c 'cd "$0" && pwd && echo Do stuff'

Ou un exemple similaire proposé par @gniourf_gniourf :

find . -type d -print0 | while IFS= read -r -d '' file; do
# ...
done

Les exemples ci-dessus prennent en charge les répertoires dont le nom contient des espaces.


Ou en assignant dans un tableau bash :

dirs=($(find . -type d))
for dir in "${dirs[@]}"; do
  cd "$dir"
  echo $PWD
done

Changement . à votre nom de dossier spécifique. Si vous n'avez pas besoin d'exécuter récursivement, vous pouvez utiliser : dirs=(*) à la place. L'exemple ci-dessus ne prend pas en charge les répertoires dont le nom contient des espaces.

Alors que @gniourf_gniourf suggéré, la seule façon correcte de mettre la sortie de find dans un tableau sans utiliser une boucle explicite sera disponible dans Bash 4.4 avec :

mapfile -t -d '' dirs < <(find . -type d -print0)

Ou pas une méthode recommandée (qui implique l'analyse syntaxique de ls ):

ls -d */ | awk '{print $NF}' | xargs -n1 sh -c 'cd $0 && pwd && echo Do stuff'

L'exemple ci-dessus ignore le répertoire actuel (comme demandé par le PO), mais il se casse sur les noms avec les espaces.

Voir aussi :

45voto

larsmans Points 167484
find . -type d -exec sh -c '(cd {} && COMMAND)' ';'

COMMAND est la commande que vous voulez exécuter. Cette commande fonctionne de manière récursive, c'est-à-dire qu'elle traverse également tous les sous-répertoires. {} désigne chaque répertoire trouvé par find dans l'ordre, et le sh -c crée un shell qui cd dans le répertoire et exécute COMMAND .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X