Ceci est beaucoup plus agréable à résoudre avec la globalisation qu'avec find.
$ cd ... # to the directory one level above the album/artist structure
$ echo */*/*.cover # lists all the covers
$ printf "%s\n" */*/*.cover # lists all the covers, one per line
Supposons maintenant que vous n’avez pas de fichiers parasites dans cette belle structure. Le répertoire en cours contient uniquement des sous-répertoires d'artiste, et ceux-ci ne contiennent que des sous-répertoires d'album. Nous pouvons alors faire quelque chose comme ceci:
$ diff <(for x in */*/cover.jpg; do echo "$(dirname "$x")" ; done) <(printf "%s\n" */*)
La syntaxe <(...)
correspond à la substitution du processus Bash: elle vous permet d'utiliser une commande à la place d'un argument de fichier. Il vous permet de traiter la sortie d'une commande comme un fichier. Nous pouvons donc exécuter deux programmes et prendre leur diff, sans enregistrer leur sortie dans des fichiers temporaires. Le programme diff
pense qu'il fonctionne avec deux fichiers, mais en fait, il lit deux canaux.
La commande qui génère l’entrée de droite dans diff
, printf "%s\n" */*
, répertorie simplement les répertoires d’album. La commande de gauche effectue une itération dans les chemins *.cover
et imprime leurs noms de répertoire.
Test de fonctionnement:
$ find . # let's see what we have here
.
./a
./a/b
./foo
./foo/bar
./foo/baz
./foo/baz/cover.jpg
$ diff <(for x in */*/cover.jpg; do echo "$(dirname "$x")" ; done) <(printf "%s\n" */*)
0a1,2
> a/b
> foo/bar
Aha, les répertoires a/b
et foo/bar
n'ont pas de cover.jpg
.
Il y a des cas de coins cassés, comme cela par défaut, *
se développe lui-même s'il ne correspond à rien. Cela peut être résolu avec set -o nullglob
de Bash.