Une -exec
commande doit être terminée par un ;
(vous devez donc généralement taper \;
ou ';'
éviter une interprétation par le shell) ou un +
. 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:
Tout d'abord, vous utilisez {};
, mais le ;
doit être un paramètre qui lui est propre.
Deuxièmement, la commande se termine à &&
. Vous avez spécifié «exécuter la recherche, et si cela a réussi, supprimez le fichier nommé {};
.». Si vous souhaitez utiliser des éléments shell dans la -exec
commande, vous devez l'exécuter explicitement dans un shell, tel que -exec sh -c 'ffmpeg ... && rm'
.
Cependant, vous ne devez pas ajouter le {} dans 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 au shell 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 que la $
chose est évaluée par le shell dans le premier exemple. Imaginez qu'il y ait un fichier appelé $(rm -rf /)
:-)
(Note latérale: le -
n'est pas nécessaire, mais la première variable après la commande est affectée à la variable $0
, qui est une variable spéciale contenant normalement le nom du programme en cours d'exécution et la définition d'un paramètre est un peu impure, même si elle a gagné ne causera probablement aucun mal ici, nous avons donc réglé cela juste -
pour commencer $1
.)
Donc, votre commande pourrait être quelque chose comme
find -exec bash -c 'ffmpeg -i "$1" -sameq "$1".mp3 && rm "$1".mp3' - {} \;
Mais il y a une meilleure façon. trouver des supports and
et or
, donc vous pouvez faire des choses comme find -name foo -or -name bar
. Mais cela fonctionne également avec -exec
, qui évalue à true si la commande se termine avec succès et à false dans le cas contraire. Voir cet exemple:
$ ls
false true
$ find * -exec {} \; -and -print
true
Il exécute l'impression uniquement si la commande a réussi, ce qu'elle a fait pour true
mais pas pour false
.
Vous pouvez donc utiliser deux instructions exec chaînées avec un -and
, et il n'exécutera ce dernier que si le premier a été exécuté avec succès.