Réponses:
Vous pouvez spécifier une barre oblique à la fin pour ne faire correspondre que les répertoires:
for d in */ ; do
echo "$d"
done
[[ -L $d ]]
si $ d est un lien symbolique.
set -P
n'affecte que les commandes qui changent de répertoire. sprunge.us/TNac
[[ -L "$f" ]]
n'exclura pas les liens symboliques dans ce cas avec */
, vous devez [[ -L "${f%/}" ]]
Vous pouvez tester avec -d
:
for f in *; do
if [ -d "$f" ]; then
# $f is a directory
fi
done
C'est l'un des opérateurs de test de fichier .
if [[ -d "$f" && ! -L "$f" ]]
exclura les liens symboliques
if [[ "$f" = "*" ]]; then continue; fi
Attention, la solution de choroba, bien qu'élégante, peut provoquer un comportement inattendu si aucun répertoire n'est disponible dans le répertoire actuel. Dans cet état, plutôt que de sauter la for
boucle, bash exécutera la boucle exactement une fois où d
est égal à */
:
#!/usr/bin/env bash
for d in */; do
# Will print */ if no directories are available
echo $d
done
Je recommande d'utiliser les éléments suivants pour vous protéger contre ce cas:
#!/usr/bin/env bash
for f in *; do
if [ -d ${f} ]; then
# Will not run if no directories are available
echo $f
fi
done
Ce code parcourt tous les fichiers du répertoire en cours, vérifie s’il f
s’agit d’un répertoire, puis indique f
si la condition renvoie true. Si f
est égal à */
, echo $f
ne sera pas exécuté.
shopt -s nullglob
.
Si vous devez sélectionner des fichiers plus spécifiques que seuls les répertoires utilisent find
, transmettez-les à while read
:
shopt -s dotglob
find * -prune -type d | while IFS= read -r d; do
echo "$d"
done
Utilisez shopt -u dotglob
pour exclure les répertoires cachés (ou setopt dotglob
/ unsetopt dotglob
dans zsh).
IFS=
pour éviter de diviser les noms de fichiers contenant l’un des $IFS
, par exemple:'a b'
voir la réponse AsymLabs ci-dessous pour plus d' find
options
edit:
au cas où vous auriez besoin de créer une valeur de sortie à partir de la boucle while, vous pouvez contourner le sous-shell supplémentaire par cette astuce:
while IFS= read -r d; do
if [ "$d" == "something" ]; then exit 1; fi
done < <(find * -prune -type d)
Vous pouvez utiliser pure bash pour cela, mais il vaut mieux utiliser find:
find . -maxdepth 1 -type d -exec echo {} \;
(trouver en outre comprendra des répertoires cachés)
shopt -s dotglob
pour bash
inclure des répertoires cachés. Le vôtre comprendra également .
. Notez également que ce -maxdepth
n'est pas une option standard ( -prune
est).
dotglob
option est intéressante mais dotglob
ne concerne que l'utilisation de *
. find .
inclura toujours les répertoires cachés (ainsi que le répertoire courant)
Ceci est fait pour trouver les répertoires visibles et cachés dans le répertoire de travail actuel, en excluant le répertoire racine:
pour simplement parcourir les répertoires:
find -path './*' -prune -type d
inclure des liens symboliques dans le résultat:
find -L -path './*' -prune -type d
faire quelque chose dans chaque répertoire (à l'exclusion des liens symboliques):
find -path './*' -prune -type d -print0 | xargs -0 <cmds>
pour exclure les répertoires cachés:
find -path './[^.]*' -prune -type d
pour exécuter plusieurs commandes sur les valeurs retournées (un exemple très artificiel):
find -path './[^.]*' -prune -type d -print0 | xargs -0 -I '{}' sh -c \
"printf 'first: %-40s' '{}'; printf 'second: %s\n' '{}'"
au lieu de 'sh -c', vous pouvez également utiliser 'bash -c', etc.
... -print0 | xargs -0 ...
si vous ne connaissez pas les noms exacts.
find * | while read file; do ...
Vous pouvez parcourir tous les répertoires, y compris les répertoires cachés (commençant par un point) sur une ligne et plusieurs commandes avec:
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
Remarque: l' utilisation de la liste */ .*/
fonctionne sous bash, mais affiche également les dossiers .
et ..
ne s'affiche pas dans zsh, mais génère une erreur s'il n'y a pas de fichier caché dans le dossier.
Une version plus propre qui inclura les répertoires cachés et exclura ../ sera avec l'option dotglob:
shopt -s dotglob
for file in */ ; do echo "$file is a directory"; done
(ou setopt dotglob
en zsh)
vous pouvez désinstaller DOTGLOB avec
shopt -u dotglob
Cela inclura le chemin complet dans chaque répertoire de la liste:
for i in $(find $PWD -maxdepth 1 -type d); do echo $i; done
Utilisez find
with -exec
pour parcourir les répertoires et appeler une fonction dans l'option exec:
dosomething () {
echo "doing something with $1"
}
export -f dosomething
find -path './*' -prune -type d -exec bash -c 'dosomething "$0"' {} \;
Utiliser shopt -s dotglob
ou shopt -u dotglob
pour inclure / exclure des répertoires cachés
ls -l | grep ^d
ou:
ll | grep ^d
Vous pouvez le définir comme un alias
ls
réponse à cette base, qui répertorie les répertoires.
ls
: mywiki.wooledge.org/ParsingLs