Dies ist mit Globbing viel besser zu lösen als mit 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
Nehmen wir nun an, Sie haben keine Streudateien in dieser schönen Struktur. Das aktuelle Verzeichnis enthält nur Interpreten-Unterverzeichnisse und diese enthalten nur Album-Unterverzeichnisse. Dann können wir so etwas machen:
$ diff <(for x in */*/cover.jpg; do echo "$(dirname "$x")" ; done) <(printf "%s\n" */*)
Die <(...)
Syntax lautet Bash-Prozessersetzung: Sie können einen Befehl anstelle eines Dateiarguments verwenden. Sie können die Ausgabe eines Befehls als Datei behandeln. Wir können also zwei Programme ausführen und deren Diff verwenden, ohne ihre Ausgabe in temporären Dateien zu speichern. Das diff
Programm glaubt, dass es mit zwei Dateien arbeitet, aber tatsächlich liest es aus zwei Pipes.
Der Befehl, der die rechte Hand eingegeben erzeugt diff
, printf "%s\n" */*
listet nur die Album - Verzeichnisse. Der Befehl für die linke Hand durchläuft die *.cover
Pfade und gibt deren Verzeichnisnamen aus.
Testlauf:
$ 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, die a/b
und foo/bar
Verzeichnisse haben keine cover.jpg
.
Es gibt einige Fälle mit unterbrochenen Ecken, die sich standardmäßig *
zu sich selbst erweitern, wenn sie mit nichts übereinstimmen. Dies kann mit Bash's behoben werden set -o nullglob
.