Будет ли это делать?
find . -name '*.avi' -type f -execdir bash -c 'f=("${0%avi}"*);((${#f[@]}==1))' {} \; -print
Я постараюсь объяснить, как это работает.
Ну, на самом деле это действительно просто: найти все файлы в текущем каталоге, чтобы имя имело расширение avi
. Для каждого из них, скажем, это файл, который X.avi
выполняет в каталоге, где находится (execdir
) команда:
bash -c 'f=("${0%avi}"*);((${#f[@]}==1))' {}
где {}
заменяется именем файла, в нашем тестовом примере X.avi
. Так что это как
bash -c 'f=("${0%avi}"*);((${#f[@]}==1))' X.avi
На этом этапе позвольте мне подчеркнуть, что это на 100% безопасно в отношении пробелов и других забавных символов в именах файлов! Теперь вы видите фрагмент, который будет выполнять bash? Я имею в виду этот фрагмент
f=("${0%avi}"*);((${#f[@]}==1))
Это будет выполнено с 0-м позиционным параметром, установленным в наше имя файла; в нашем тестовом примере это X.avi
.
Часть "${0%avi}"
расширяется до имени файла, с удаленным конечным avi
(кстати, это имя файла гарантированно будет иметь это расширение в этой точке), а часть "${0%avi}"*
будет расширяться ко всем файлам в текущем каталоге (помните, тот, который содержит файл), которые имеют расширение .avi
. В нашем тестовом примере это выглядит так:
X.*
Затем мы строим массив f
из них и, наконец, успешно завершаем этот процесс bash
если f
содержит только один элемент (так что, весьма вероятно, f
содержит только X.avi
в нашем тестовом примере), и в противном случае происходит сбой. Если это было успешно, мы печатаем имя файла.