найти: отсутствует аргумент для -exec - PullRequest
185 голосов
/ 03 июня 2010

Сегодня мне выручили с помощью команды, но, похоже, она не работает. Это команда:

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 && rm {}\;

Оболочка возвращает

find: missing argument to `-exec'

В основном я пытаюсь рекурсивно просмотреть каталог (если он имеет другие каталоги) и выполнить команду ffmpeg для типов файлов .rm и преобразовать их в типы .mp3. Как только это будет сделано, удалите файл .rm, который был только что преобразован.

Я ценю любую помощь в этом.

Ответы [ 9 ]

307 голосов
/ 03 июня 2010
Команда

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

Ваша команда имеет две ошибки:

Сначала вы используете {};, но ; должен быть собственным параметром.

Во-вторых, команда заканчивается на &&. Вы указали «выполнить поиск, и, если это было успешно, удалите файл с именем {};.«. Если вы хотите использовать содержимое оболочки в команде -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, который оценивается как истина, если команда успешно завершается, и ложь, если нет. Смотрите этот пример:

$ ls
false  true
$ find * -exec {} \; -and -print
true

Печать выполняется только в том случае, если команда была успешно выполнена, что она сделала для true, но не для false.

Таким образом, вы можете использовать два оператора exec, связанные с -and, и он будет выполнять последний, только если первый был успешно выполнен.

52 голосов
/ 03 июня 2010

Я понял это сейчас. Когда вам нужно запустить две команды в exec в находке, вам нужно иметь два отдельных исполнителя. Это, наконец, сработало для меня.

find . -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 \; -exec rm {} \;
47 голосов
/ 04 августа 2014

Попробуйте поставить пробел перед каждым \;

Работы:

find . -name "*.log" -exec echo {} \;

Не работает:

find . -name "*.log" -exec echo {}\;
7 голосов
/ 03 сентября 2015

Только для вашей информации:
Я только что попытался использовать команду "find -exec" в системе Cygwin (UNIX эмулируется в Windows), и там кажется, что необходимо удалить обратную косую черту перед точкой с запятой:
find ./ -name "blabla" -exec wc -l {} ;

2 голосов
/ 03 марта 2016

Также, если у кого-то еще есть «find: отсутствующий аргумент для -exec», это может помочь:

В некоторых оболочках вам не нужно выполнять экранирование, т. Е. Вам не нужно "\" перед ";".

find <file path> -name "myFile.*" -exec rm - f {} ;
2 голосов
/ 29 сентября 2015

На тот случай, если кто-нибудь увидит подобные «отсутствующие аргументы -exec» в сценариях 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
1 голос
/ 03 июня 2010

Я думаю, тебе нужно сбежать.

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} \-sameq {}.mp3 \&\& rm {}\;
0 голосов
/ 05 января 2017

Если вы все еще получаете «find: отсутствует аргумент для -exec», попробуйте заключить аргумент execute в кавычки.

find <file path> -type f -exec "chmod 664 {} \;"
0 голосов
/ 03 июня 2010

И {}, и && вызовут проблемы из-за расширения в командной строке. Я бы предложил попробовать:

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i \{} -sameq \{}.mp3 \; -exec rm \{} \;
...