-exec
Команда повинна бути припинена з ;
(так зазвичай потрібно ввести \;
або , ';'
щоб уникнути interpretion оболонки) або +
. Різниця полягає в тому, що з ;
, команда викликається один раз на файл, з +
, вона викликається якомога менше разів (як правило, один раз, але для командного рядка є максимальна довжина, тому вона може бути розділена) з усіма назви файлів . Дивіться цей приклад:
$ cat /tmp/echoargs
#!/bin/sh
echo $1 - $2 - $3
$ find /tmp/foo -exec /tmp/echoargs {} \;
/tmp/foo - -
/tmp/foo/one - -
/tmp/foo/two - -
$ find /tmp/foo -exec /tmp/echoargs {} +
/tmp/foo - /tmp/foo/one - /tmp/foo/two
У вашій команді є дві помилки:
По-перше, ви використовуєте {};
, але ;
повинен бути власний параметр.
По-друге, команда закінчується на &&
. Ви вказали "запустити пошук, і якщо це було успішним, видаліть файл з назвою {};
." Якщо ви хочете використовувати в -exec
команді речі оболонки , вам потрібно явно запустити її в оболонці, наприклад -exec sh -c 'ffmpeg ... && rm'
.
Однак не слід додавати {} всередину команди bash, це створюватиме проблеми, коли є спеціальні символи. Натомість ви можете передавати додаткові параметри оболонці після -c command_string
(див. man sh
):
$ ls
$(echo damn.)
$ find * -exec sh -c 'echo "{}"' \;
damn.
$ find * -exec sh -c 'echo "$1"' - {} \;
$(echo damn.)
Ви бачите, що $
річ оцінюється оболонкою в першому прикладі. Уявіть, що був файл з назвою $(rm -rf /)
:-)
(Бічна примітка: The -
не потрібна, але перша змінна після команди присвоюється змінній $0
, яка є спеціальною змінною, яка зазвичай містить ім'я запущеної програми і встановлює, що параметр трохи нечистий, хоча він виграв Мабуть, тут не завдасть ніякої шкоди, тому ми встановимо це як раз -
і почнемо з цього $1
.)
Тож ваша команда могла бути чимось на кшталт
find -exec bash -c 'ffmpeg -i "$1" -sameq "$1".mp3 && rm "$1".mp3' - {} \;
Але є кращий спосіб. знайти підтримку and
та or
, тому ви можете робити подібні речі find -name foo -or -name bar
. Але це також працює з -exec
, що оцінює істинне, якщо команда успішно закінчується, і хибне, якщо ні. Дивіться цей приклад:
$ ls
false true
$ find * -exec {} \; -and -print
true
Він виконує друк лише в тому випадку, якщо команда була успішно виконана, але для цього true
вона не була зроблена false
.
Таким чином, ви можете використовувати два оператори exec, пов’язані з ланцюгом -and
, і він буде виконувати останній лише у тому випадку, коли перший був успішно запущений.