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.
-and
et-or
ne sont pas portables. POSIX spécifie-a
et-o
, et en fait-a
est toujours supposé (donc pas nécessaire)."\;"
ne fonctionne pas mais" \;"
fonctionneJe l'ai compris maintenant. Lorsque vous devez exécuter deux commandes dans exec dans une recherche, vous devez en fait avoir deux execs distincts. Cela a finalement fonctionné pour moi.
la source
echo
avant les commandes et voyez ce qu'il fait.echo
est assez peu fiable - vous ne pouvez pas faire la différence entreecho "one argument"
etecho one argument
(la sortie de ce dernier étant fausse, car elle passe en faitecho
deux arguments complètement séparés). Il vaut bien mieux faire quelque chose comme-exec bash -c 'printf "%q " "$@"' _ ffmpeg -i {} -sameq {}.mp3 \; -printf '\n'
, qui imprimera la sortie d'une manière qui rendra les caractères non imprimables visibles afin que vous puissiez détecter les sauts de ligne DOS et autres bizarreries.Essayez de mettre un espace avant chaque \;
Travaux:
Ne fonctionne pas:
la source
Juste pour votre information:
je viens d'essayer d'utiliser la commande "find -exec" sur un système Cygwin (émulé UNIX sur Windows), et il semble que la barre oblique inverse avant le point-virgule doit être supprimée:
find ./ -name "blabla" -exec wc -l {} ;
la source
find /etc/nginx -name '*.conf' -exec echo {} ;
et afind /etc/nginx -name '*.conf' -exec echo {}\;
donné le même résultat. :({}
.Juste au cas où quelqu'un verrait un "argument -exec manquant" similaire dans les scripts bash d'Amazon Opsworks Chef, j'avais besoin d'ajouter une autre barre oblique inverse pour échapper au \;
la source
De plus, si quelqu'un d'autre a l'argument "find: missing to -exec", cela pourrait aider:
Dans certains shells, vous n'avez pas besoin de vous échapper, c'est-à-dire que vous n'avez pas besoin du "\" devant le ";".
la source
;
ne pas être cité ou échappé ici signifie qu'il peut être consommé par le shell, et non lu parfind
. Aussi,-f
et ce- f
sont deux choses différentes.Vous devez vous échapper, je pense.
la source
{} Et && causeront des problèmes en raison de l'extension de la ligne de commande. Je suggère d'essayer:
la source
{}
variable pour supprimer le bon fichier?{}
? Sauf s'il contient deux points ou virgules qui resteront tels quels.Vous devez mettre un espace entre
{}
et\;
La commande sera donc comme:
la source
Si vous obtenez toujours "find: argument manquant à -exec", essayez de placer l'argument d'exécution entre guillemets.
la source