A -exec
doit être terminée par un ;
(vous devez donc généralement taper \;
ou ';'
pour éviter l'interprétation par l'interpréteur de commandes) ou un fichier +
. La différence est qu'avec ;
la commande est appelée une fois par fichier, avec +
elle est appelée aussi peu de fois que possible (généralement une fois, mais il y a une longueur maximale pour une ligne de commande, donc elle peut être divisée) avec tous les noms de fichiers. Voir cet exemple :
$ 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
Votre commande comporte deux erreurs :
D'abord, vous utilisez {};
mais le ;
doit être un paramètre qui lui est propre.
Deuxièmement, la commande se termine à la &&
. Vous avez spécifié "run find", et si cela a réussi, supprimer le fichier nommé {};
.". Si vous voulez utiliser des éléments du shell dans le -exec
vous devez l'exécuter explicitement dans un shell, tel que -exec sh -c 'ffmpeg ... && rm'
.
Cependant, vous ne devriez pas ajouter les {} à l'intérieur de la commande bash, cela produira des problèmes lorsqu'il y a des caractères spéciaux. Au lieu de cela, vous pouvez passer des paramètres supplémentaires à l'interpréteur de commandes après -c command_string
(voir man sh
) :
$ ls
$(echo damn.)
$ find * -exec sh -c 'echo "{}"' \;
damn.
$ find * -exec sh -c 'echo "$1"' - {} \;
$(echo damn.)
Vous voyez le $
est évalué par le shell dans le premier exemple. Imaginez qu'il y ait un fichier appelé $(rm -rf /)
:-)
(Note complémentaire : le -
n'est pas nécessaire, mais la première variable après la commande est assignée à la variable $0
Il s'agit d'une variable spéciale contenant normalement le nom du programme en cours d'exécution et le fait de la définir comme paramètre est un peu impur, même si cela ne causera probablement aucun dommage ici. -
et commencer par $1
.)
Votre commande pourrait donc être quelque chose comme
find -exec bash -c 'ffmpeg -i "$1" -sameq "$1".mp3 && rm "$1".mp3' - {} \;
Mais il y a un meilleur moyen. Trouvez des supports and
et or
donc vous pouvez faire des choses comme find -name foo -or -name bar
. Mais cela fonctionne aussi avec -exec
qui est évalué à true si la commande se termine avec succès, et à false sinon. Voir cet exemple :
$ ls
false true
$ find * -exec {} \; -and -print
true
Il n'exécute l'impression que si la commande s'est déroulée avec succès, ce qui a été le cas pour true
mais pas pour false
.
Vous pouvez donc utiliser deux instructions exec enchaînées avec une instruction -and
et il n'exécutera la seconde que si la première a été exécutée avec succès.