É muito melhor resolver com globbing do que com 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
Agora, suponha que você não tenha arquivos perdidos nessa bela estrutura. O diretório atual contém apenas subdiretórios de artistas e esses contêm apenas subdiretórios de álbuns. Então podemos fazer algo assim:
$ diff <(for x in */*/cover.jpg; do echo "$(dirname "$x")" ; done) <(printf "%s\n" */*)
A <(...)
sintaxe é a substituição do processo Bash: permite usar um comando no lugar de um argumento de arquivo. Permite tratar a saída de um comando como um arquivo. Portanto, podemos executar dois programas e obter as diferenças deles, sem salvar sua saída em arquivos temporários. O diff
programa pensa que está trabalhando com dois arquivos, mas na verdade está lendo de dois canais.
O comando que produz a entrada de mão direita para diff
, printf "%s\n" */*
, apenas lista os diretórios do álbum. O comando à esquerda percorre os *.cover
caminhos e imprime seus nomes de diretório.
Execução de teste:
$ 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, os diretórios a/b
e foo/bar
não têm cover.jpg
.
Existem alguns casos de esquina quebrados, como se por padrão se *
expandisse para si mesmo se não corresponder a nada. Isso pode ser resolvido com o Bash's set -o nullglob
.