J'ai une question fondamentale sur le fonctionnement de bash et une question pratique connexe.
Question fondamentale: supposons que je suis dans un répertoire qui a trois sous-répertoires: a, b et c.
le code
for dir in $(ls)
do
echo $dir
done
crache:
a b c
a b c
a b c
i.e, dir
stocke toujours une liste de tous les fichiers/répertoires de ma cwd
. Ma question est: pourquoi dans le monde cela serait-il pratique? À mon avis, il est beaucoup plus utile et intuitif d’avoir dir
de stocker chaque élément à la fois, c’est-à-dire que j’aimerais avoir une sortie.
a
b
c
En outre, selon l'une des réponses - il est faux d'utiliser for dir in $(ls)
, mais lorsque j'utilise for dir in $(ls -l)
, je reçois encore plus de copies de a b c
(plus qu'il n'y a de répertoires/fichiers dans le cwd). Pourquoi donc?
Ma deuxième question est pratique: comment puis-je parcourir tous les répertoires (pas les fichiers!) De ma cwd
qui commencent par majuscule W? J'ai commencé avec
for dir in `ls -l W*`
mais cela échoue car a) la raison de la question 1 et b) car elle n'exclut pas les fichiers. Suggestions appréciées.
Ne jamais analyser la sortie de ls
comme ceci ( Pourquoi ne pas analyser la sortie de ls (1) ).
De plus, votre syntaxe est fausse. Vous ne voulez pas dire ()
, vous voulez dire $()
.
Cela dit, vous feriez une boucle sur les répertoires commençant par W (ou utilisez plutôt la commande find
, selon votre scénario):
for path in /my/path/W*; do
[ -d "${path}" ] || continue # if not a directory, skip
dirname="$(basename "${path}")"
do_stuff
done
Quant à la sortie que vous obtenez de la mauvaise boucle ls, elle ne devrait pas ressembler à cela. Ceci est la sortie attendue et montre pourquoi vous ne voulez pas utiliser ls en premier lieu:
$ find
.
./c
./a
./foo bar
./b
$ type ls
ls is hashed (/bin/ls)
$ for x in $(ls); do echo "${x}"; done
a
b
c
foo
bar
Cela devrait fonctionner:
shopt -s nullglob # empty directory will return empty list
for dir in ./*/;do
echo "$dir" # dir is directory only because of the / after *
done
Pour être également récursif dans les sous-répertoires, utilisez globstar
:
shopt -s globstar nullglob
for dir in ./**/;do
echo "$dir" # dir is directory only because of the / after **
done
Vous pouvez faire en sorte que la méthode de @Adrian Frühwirths soit récursive en sous-répertoires en utilisant aussi globstar
:
shopt -s globstar
for dir in ./**;do
[[ ! -d $dir ]] && continue # if not directory then skip
echo "$dir"
done
globstar
Si défini, le modèle ‘**’ utilisé dans un contexte d’extension de nom de fichier sera correspond à tous les fichiers et à zéro ou plusieurs répertoires et sous-répertoires. Si le motif est suivi de ‘/’, uniquement des répertoires et des sous-répertoires rencontre.
nullglob
Si défini, Bash autorise le développement de modèles de nom de fichier qui ne correspondent à aucun fichier à une chaîne nulle, plutôt qu'eux-mêmes.
Eh bien, vous savez que ce que vous voyez n’est pas ce que vous attendez. La sortie que vous voyez ne provient pas de la commande echo, mais de la commande dir.
Essayez ce qui suit:
ls -1 | while read line; do
if [-d "$line" ] ; then
echo $line
fi
done
for files in $(ls) ; do
if [-d "$files" ] ; then
echo $files
fi
done