246 votes

Comment boucler sur les répertoires sous Linux ?

J'écris un script en bash sous Linux et j'ai besoin de parcourir tous les noms de sous-répertoires dans un répertoire donné. Comment puis-je parcourir ces répertoires en boucle (et sauter les fichiers réguliers) ?

Par exemple :
le répertoire donné est /tmp/
il comporte les sous-répertoires suivants : /tmp/A, /tmp/B, /tmp/C

Je veux récupérer A, B, C.

0 votes

0 votes

Réseau solide sous bash (en acceptant les noms de domaine espacés) : dirs=(/tmp/*/);dirs=("${dirs[@]%/}");dirs=("${dirs[@]#/tmp/}‌​") entonces printf "%s\n" "${dirs[@]}" o for dir in "${dirs[@]}" ;do ...

590voto

ghostdog74 Points 86060

Toutes les réponses jusqu'à présent utilisent find alors en voici une avec juste la coquille. Pas besoin d'outils externes dans votre cas :

for dir in /tmp/*/     # list directories in the form "/tmp/dirname/"
do
    dir=${dir%*/}      # remove the trailing "/"
    echo "${dir##*/}"    # print everything after the final "/"
done

4 votes

Eh bien, oui, 'find' est en quelque sorte le couteau suisse sur les machines *NIX pour trouver quelque chose en rapport avec un fichier. Mais une version pure avec uniquement des buildins bash est bonne à savoir, aussi. +1

27 votes

+1 - Pourquoi s'embêter avec find quand vous pouvez ajouter une barre oblique à un caractère générique

32 votes

Así que for dir in */; do echo $dir; done est pour les répertoires dans le répertoire courant.

146voto

Boldewyn Points 29961
cd /tmp
find . -maxdepth 1 -mindepth 1 -type d -printf '%f\n'

Une brève explication :

  • find trouve des fichiers (de toute évidence)

  • . est le répertoire courant, qui après le cd est /tmp (à mon avis, c'est plus flexible que d'avoir /tmp directement dans le find commande. Vous n'avez qu'un seul endroit, le cd à changer, si vous voulez que d'autres actions aient lieu dans ce dossier)

  • -maxdepth 1 y -mindepth 1 s'assurer que find ne regarde que dans le répertoire courant et n'inclut pas . dans le résultat

  • -type d ne recherche que les répertoires

  • -printf '%f\n imprime uniquement le nom du dossier trouvé (plus une nouvelle ligne) pour chaque résultat.

Et voilà !

0 votes

Au fait : Notez, que toutes les réponses trouveront les dossiers cachés, aussi (c'est-à-dire, les dossiers commençant par un point) ! Si vous ne voulez pas cela, ajoutez ` -regex ' \. /[^ \. ].*'` avant les options printf ou exec.

1 votes

Utile - si vous avez besoin d'exécuter une seule commande pour chaque coup ;-) - Seulement j'ai plusieurs commandes à exécuter :-( .

1 votes

Pas de problème : adaptez cette solution : transnum.blogspot.de/2008/11/ A l'intérieur de la while..done la boucle peut devenir folle.

62voto

rubo77 Points 1502

Vous pouvez parcourir en boucle tous les répertoires, y compris les répertoires cachés (commençant par un point) avec :

for file in */ .*/ ; do echo "$file is a directory"; done

note : en utilisant la liste */ .*/ ne fonctionne dans zsh que s'il existe au moins un répertoire caché dans le dossier. En bash, il affichera également . y ..


Une autre possibilité pour bash d'inclure des répertoires cachés serait d'utiliser :

shopt -s dotglob;
for file in */ ; do echo "$file is a directory"; done

Si vous voulez exclure les liens symboliques :

for file in */ ; do 
  if [[ -d "$file" && ! -L "$file" ]]; then
    echo "$file is a directory"; 
  fi; 
done

Pour n'afficher que le nom du répertoire de queue (A,B,C en question) dans chaque solution, utilisez ceci dans les boucles :

file="${file%/}"     # strip trailing slash
file="${file##*/}"   # strip path and leading slash
echo "$file is the directoryname without slashes"

Exemple (cela fonctionne également avec les répertoires qui contiennent des espaces) :

mkdir /tmp/A /tmp/B /tmp/C "/tmp/ dir with spaces"
for file in /tmp/*/ ; do file="${file%/}"; echo "${file##*/}"; done

0 votes

@richardec : merci pour la prime ! Comment ai-je obtenu cet honneur ?

23voto

zpon Points 518

Fonctionne avec les répertoires qui contiennent des espaces

Inspiré par Sorpigal

while IFS= read -d $'\0' -r file ; do 
    echo $file; ls $file ; 
done < <(find /path/to/dir/ -mindepth 1 -maxdepth 1 -type d -print0)

Original post (Ne fonctionne pas avec les espaces)

Inspiré par Boldewyn : Exemple de boucle avec find commandement.

for D in $(find /path/to/dir/ -mindepth 1 -maxdepth 1 -type d) ; do
    echo $D ;
done

9voto

find . -mindepth 1 -maxdepth 1 -type d -printf "%P\n"

0 votes

C'est bien aussi et cela élimine le besoin de basename . Je préfère cela à ma réponse.

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