Это гораздо приятнее решать с помощью шатания, чем с помощью поиска.
$ 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
Теперь предположим, что у вас нет случайных файлов в этой хорошей структуре. Текущий каталог содержит только подкаталоги исполнителя, а те содержат только подкаталоги альбома. Тогда мы можем сделать что-то вроде этого:
$ diff <(for x in */*/cover.jpg; do echo "$(dirname "$x")" ; done) <(printf "%s\n" */*)
<(...)
Синтаксис подстановки процесса Bash: она позволяет использовать команду вместо файла аргумента. Это позволяет вам обрабатывать вывод команды как файл. Таким образом, мы можем запустить две программы и взять их разность, не сохраняя их вывод во временных файлах. diff
Программа считает , что она работает с двумя файлами, но на самом деле это чтение из двух труб.
Команда , которая производит правильный вход руки в diff
, printf "%s\n" */*
просто перечисляет альбом каталоги. Левая команда перебирает *.cover
пути и печатает их имена каталогов.
Тестовый забег:
$ 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
Ага, то a/b
и foo/bar
каталогов нету cover.jpg
.
Есть несколько случаев с разбитыми углами, например, которые по умолчанию *
расширяются, если ничего не совпадают. Это можно решить с помощью Баш set -o nullglob
.