Cela fonctionnera dans Bash 4:
ls -l {,**/}*.ext
Pour que le glob double astérisque fonctionne, l' globstar
option doit être définie (par défaut: activé):
shopt -s globstar
De man bash
:
globstar
S'il est défini, le modèle ** utilisé dans une extension de nom de fichier
le texte correspondra à un fichier et à zéro ou plusieurs répertoires et
sous-répertoires. Si le motif est suivi d'un /, seulement
les répertoires et les sous-répertoires correspondent.
Maintenant, je me demande s'il peut y avoir eu un bogue dans le traitement de globstar, car maintenant, en utilisant simplement, j'obtiens des ls **/*.ext
résultats corrects.
Quoi qu'il en soit, j'ai regardé l' analyse kenorb en utilisant le référentiel VLC et trouvé des problèmes avec cette analyse et dans ma réponse immédiatement ci-dessus:
Les comparaisons avec la sortie de la find
commande ne sont pas valides car la spécification -type f
n'inclut pas d'autres types de fichiers (répertoires en particulier) et les ls
commandes listées le font probablement. De plus, l'une des commandes répertoriées, ls -1 {,**/}*.*
- qui semble être basée sur la mienne ci-dessus, ne renvoie que les noms qui incluent un point pour les fichiers qui se trouvent dans des sous-répertoires. La question de l'OP et ma réponse comportent un point puisque ce qui est recherché, ce sont des fichiers avec une extension spécifique.
Le plus important, cependant, est qu'il y a un problème spécial lors de l'utilisation de la ls
commande avec le modèle globstar **
. De nombreux doublons surviennent car le modèle est étendu par Bash à tous les noms de fichiers (et noms de répertoires) dans l'arborescence examinée. Suite à l'expansion, la ls
commande répertorie chacun d'entre eux et leur contenu s'il s'agit de répertoires.
Exemple:
Dans notre répertoire actuel se trouve le sous-répertoire A
et son contenu:
A
└── AB
└── ABC
├── ABC1
├── ABC2
└── ABCD
└── ABCD1
Dans cet arbre, se **
développe en "AA / AB A / AB / ABC A / AB / ABC / ABC1 A / AB / ABC / ABC2 A / AB / ABC / ABCD A / AB / ABC / ABCD / ABCD1" (7 entrées) . Si vous le faites, echo **
c'est la sortie exacte que vous obtiendrez et chaque entrée est représentée une fois. Cependant , si vous le faites, ls **
il affichera une liste de chacune de ces entrées. Donc, essentiellement, il est ls A
suivi de ls A/AB
, etc., donc il A/AB
est montré deux fois. De plus, ls
va séparer la sortie de chaque sous-répertoire:
...
<blank line>
directory name:
content-item
content-item
Donc, utiliser wc -l
compte toutes ces lignes vides et ces en-têtes de section de nom de répertoire, ce qui jette le décompte encore plus loin.
C'est une autre raison pour laquelle vous ne devriez pas analyserls
.
À la suite de cette analyse plus approfondie, je recommande de ne pas utiliser le modèle globstar dans des circonstances autres que l'itération sur une arborescence de fichiers de cette manière:
for entry in **
do
something "$entry"
done
En guise de comparaison finale, j'ai utilisé un référentiel de sources Bash que j'avais sous la main et j'ai fait ceci:
shopt -s globstar dotglob
diff <(echo ** | tr ' ' '\n') <(find . | sed 's|\./||' | sort)
0a1
> .
J'avais l'habitude tr
de changer les espaces en nouvelles lignes, ce qui n'est valable qu'ici car aucun nom n'inclut d'espace. J'avais l'habitude sed
de supprimer le début ./
de chaque ligne de sortie find
. J'ai trié la sortie find
car elle n'est normalement pas triée et l'expansion des globs de Bash est déjà triée. Comme vous pouvez le voir, la seule sortie de diff
était la .
sortie du répertoire courant par find
. Quand j'ai fait ls ** | wc -l
la sortie avait presque deux fois plus de lignes.
**/*.ext
. Êtes-vous sûr que cela fonctionne pour vous?