Um -exec
comando deve ser finalizado com a ;
(portanto, você geralmente precisa digitar \;
ou ';'
evitar a interpretação pelo shell) ou a +
. A diferença é que ;
, com , o comando é chamado uma vez por arquivo, com +
, é chamado apenas o menor número de vezes possível (geralmente uma vez, mas existe um comprimento máximo para uma linha de comando, portanto pode ser dividido) com todos os nomes de arquivos . Veja este exemplo:
$ 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
Seu comando possui dois erros:
Primeiro, você usa {};
, mas ;
deve ser um parâmetro próprio.
Segundo, o comando termina no &&
. Você especificou "executar localização e, se isso tiver sido bem-sucedido, remova o arquivo chamado {};
.". Se você deseja usar itens de shell no -exec
comando, é necessário executá-lo explicitamente em um shell, como -exec sh -c 'ffmpeg ... && rm'
.
No entanto, você não deve adicionar o {} dentro do comando bash, ele produzirá problemas quando houver caracteres especiais. Em vez disso, você pode passar parâmetros adicionais para o shell depois -c command_string
(consulte man sh
):
$ ls
$(echo damn.)
$ find * -exec sh -c 'echo "{}"' \;
damn.
$ find * -exec sh -c 'echo "$1"' - {} \;
$(echo damn.)
Você vê que a $
coisa é avaliada pelo shell no primeiro exemplo. Imagine que havia um arquivo chamado $(rm -rf /)
:-)
(Observação: -
não é necessária, mas a primeira variável após o comando ser atribuída à variável $0
, que é uma variável especial que normalmente contém o nome do programa que está sendo executado e a configuração para um parâmetro é um pouco impura, embora tenha vencido provavelmente não causará nenhum dano aqui, portanto, definimos isso apenas para -
começar $1
.)
Portanto, seu comando pode ser algo como
find -exec bash -c 'ffmpeg -i "$1" -sameq "$1".mp3 && rm "$1".mp3' - {} \;
Mas há uma maneira melhor. encontre suportes and
e or
, para que você possa fazer coisas assim find -name foo -or -name bar
. Mas isso também funciona com -exec
, que avalia como true se o comando sair com êxito e false se não. Veja este exemplo:
$ ls
false true
$ find * -exec {} \; -and -print
true
Ele somente executa a impressão se o comando foi bem-sucedido, o que foi feito, true
mas não para false
.
Portanto, você pode usar duas instruções exec encadeadas com an -and
e ela somente executará a segunda se a primeira tiver sido executada com êxito.