Ответ 1
Я понял это сейчас. Когда вам нужно запустить две команды в exec в find, вам нужно фактически иметь два отдельных exec. Это, наконец, помогло мне.
find . -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 \; -exec rm {} \;
Мне помогли сегодня с командой, но, похоже, она не работает. Это команда:
find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 && rm {}\;
Оболочка возвращает
find: missing argument to `-exec'
То, что я в основном пытаюсь сделать, - это рекурсивно переходить через каталог (если у него есть другие каталоги) и запускать команду ffmpeg в типах файлов .rm
и преобразовывать их в типы файлов .mp3
. Как только это будет сделано, удалите только что преобразованный файл .rm
.
Я ценю любую помощь в этом.
Я понял это сейчас. Когда вам нужно запустить две команды в exec в find, вам нужно фактически иметь два отдельных exec. Это, наконец, помогло мне.
find . -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 \; -exec rm {} \;
A -exec
должна быть прервана с помощью ;
(поэтому вам обычно нужно вводить \;
или ';'
, чтобы избежать интерпретации оболочки) или +
. Разница в том, что при ;
команда вызывается один раз для каждого файла, с +
она вызывается как можно меньше раз (как правило, один раз, но максимальная длина для командной строки, поэтому она может быть разделить) со всеми именами файлов. См. Этот пример:
$ 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
Ваша команда имеет две ошибки:
Сначала вы используете {};
, но ;
должен быть собственным параметром.
Во-вторых, команда заканчивается на &&
. Вы указали "запустить find", и если это было успешно, удалите файл с именем {};
. ". Если вы хотите использовать материал оболочки в команде -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 /)
: -)
(Боковое примечание: -
не требуется, но первая переменная после команды назначается переменной $0
, которая является специальной переменной, обычно содержащей имя запускаемой программы и устанавливающей ее для параметр немного нечист, хотя это, вероятно, не навредит, поэтому мы установили это только на -
и начнем с $1
.)
Таким образом, ваша команда может быть чем-то вроде
find -exec bash -c 'ffmpeg -i "$1" -sameq "$1".mp3 && rm "$1".mp3' - {} \;
Но есть лучший способ. найдите опоры and
и or
, поэтому вы можете делать такие вещи, как find -name foo -or -name bar
. Но это также работает с -exec
, который оценивает значение true, если команда успешно завершена, а false, если нет. См. Этот пример:
$ ls
false true
$ find * -exec {} \; -and -print
true
Он запускает печать только в том случае, если команда была успешно выполнена, что было сделано для true
, но не для false
.
Таким образом, вы можете использовать два оператора exec, привязанные к -and
, и он будет выполнять только последний, если первый был успешно запущен.
Попробуйте помещать пробел перед каждым \;
Работы:
find . -name "*.log" -exec echo {} \;
Не работает:
find . -name "*.log" -exec echo {}\;
Только для вашей информации:
Я просто попытался использовать команду "find -exec" в системе Cygwin (UNIX, эмулируемая в Windows), и там кажется, что обратная косая черта перед точкой с запятой должна быть удалена: find ./ -name "blabla" -exec wc -l {} ;
На всякий случай, когда кто-либо видит похожие "недостающие -exec args" в скриптах Amazon Opsworks Chef bash, мне нужно было добавить еще одну обратную косую черту, чтобы избежать \\
bash 'remove_wars' do
user 'ubuntu'
cwd '/'
code <<-EOH
find /home/ubuntu/wars -type f -name "*.war" -exec rm {} \\;
EOH
ignore_failure true
end
Кроме того, если у кого-то еще есть "find: missing argument to -exec", это может помочь:
В некоторых оболочках вам не нужно выполнять экранирование, т.е. вам не нужно "\" перед ";".
find <file path> -name "myFile.*" -exec rm - f {} ;
Думаю, вам нужно немного ускользнуть.
find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} \-sameq {}.mp3 \&\& rm {}\;
Оба {} и && вызовет проблемы из-за расширения командной строки. Я бы предложил попробовать:
find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i \{} -sameq \{}.mp3 \; -exec rm \{} \;
Если вы все еще получаете "find: missing argument to -exec", попробуйте обернуть аргумент execute в кавычки.
find <file path> -type f -exec "chmod 664 {} \;"