J'écris un script en bash sous Linux et je dois passer en revue tous les noms de sous-répertoires d'un répertoire donné. Comment puis-je parcourir ces répertoires (et ignorer les fichiers normaux)?
Par exemple:
le répertoire donné est /tmp/
il a les sous-répertoires suivants: /tmp/A, /tmp/B, /tmp/C
Je veux récupérer A, B, C.
cd /tmp
find . -maxdepth 1 -mindepth 1 -type d -printf '%f\n'
Une brève explication: find
trouve les fichiers (bien évidemment)
. est le répertoire courant, après le cd, il s’agit de /tmp
(à mon humble avis, c’est plus souple que d’avoir /tmp
directement dans la commande find. Vous n’avez qu’un seul emplacement, le cd
, à modifier, si vous voulez plus d'actions dans ce dossier)
-maxdepth 1
et -mindepth 1
assurez-vous que find
ne regarde réellement que dans le répertoire en cours et n'inclut pas '.
' dans le résultat.
-type d
ne cherche que des répertoires
-printf '%f\n
imprime uniquement le nom du dossier trouvé (plus une nouvelle ligne) pour chaque résultat.
E voila!
Jusqu'à présent, toutes les réponses utilisent find
, alors voici l'une d'entre elles avec juste le shell. 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
Vous pouvez parcourir tous les répertoires, y compris les répertoires masqués (commençant par un point) avec:
for file in */ .*/ ; do echo "$file is a directory"; done
note: en utilisant la liste */ .*/
ne fonctionne avec zsh que s’il existe au moins un répertoire caché dans le dossier. En bash, il affichera également .
et ..
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 souhaitez exclure les liens symboliques:
for file in */ ; do
if [[ -d "$file" && ! -L "$file" ]]; then
echo "$file is a directory";
fi;
done
Pour sortir uniquement le nom du répertoire de fin (A, B, C comme interrogé) 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"
mkdir /tmp/A /tmp/B /tmp/C "/tmp/ dir with spaces"
for file in /tmp/*/ ; do file="${file%/}"; echo "${file##*/}"; done
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)
Inspiré par Boldewyn : Exemple de boucle avec la commande find
.
for D in $(find /path/to/dir/ -mindepth 1 -maxdepth 1 -type d) ; do
echo $D ;
done
find . -mindepth 1 -maxdepth 1 -type d -printf "%P\n"
La technique que j'utilise le plus souvent est find | xargs
. Par exemple, si vous voulez que tous les fichiers de ce répertoire et de tous ses sous-répertoires soient lisibles par tout le monde, vous pouvez faire:
find . -type f -print0 | xargs -0 chmod go+r
find . -type d -print0 | xargs -0 chmod go+rx
L'option -print0
se termine par un caractère NULL au lieu d'un espace. L'option -0
divise son entrée de la même manière. C'est donc la combinaison à utiliser sur des fichiers avec des espaces.
Vous pouvez imaginer que cette chaîne de commandes prend chaque sortie de ligne avec find
et la colle à la fin d'une commande chmod
.
Si la commande que vous voulez exécuter en tant qu'argument au milieu plutôt qu'à la fin, vous devez être un peu créatif. Par exemple, je devais changer de répertoire et lancer la commande latemk -c
. Alors j'ai utilisé (de Wikipedia ):
find . -type d -depth 1 -print0 | \
xargs -0 sh -c 'for dir; do pushd "$dir" && latexmk -c && popd; done' fnord
Cela a pour effet de for dir $(subdirs); do stuff; done
, mais est sans danger pour les répertoires avec des espaces dans leurs noms. De plus, les appels séparés à stuff
sont effectués dans le même shell. C'est pourquoi, dans ma commande, nous devons revenir au répertoire actuel avec popd
.
find . -type d -maxdepth 1
une boucle minimale bash que vous pouvez créer (basée sur la réponse ghostdog74)
for dir in directory/*
do
echo ${dir}
done
compresser tout un tas de fichiers par répertoire
for dir in directory/*
do
Zip -r ${dir##*/} ${dir}
done