trouver: argument manquant à -exec


206

J'ai été aidé aujourd'hui avec une commande, mais cela ne semble pas fonctionner. Voici la commande:

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

Le shell revient

find: missing argument to `-exec'

Ce que j'essaie essentiellement de faire est de parcourir un répertoire récursivement (s'il a d'autres répertoires) et d'exécuter la commande ffmpeg sur les .rmtypes de fichiers et de les convertir en .mp3types de fichiers. Une fois cela fait, supprimez le .rmfichier qui vient d'être converti.

J'apprécie toute aide à ce sujet.

Réponses:


340

Une -execcommande 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 -execcommande, 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 andet 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 truemais 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.


3
La clé semble être la ligne de Marian de "the; is a arg on its own", c'est ce qui l'a fait pour moi, en ce qui concerne les ampoules et pour mon exemple de code. Merci.
pjammer

3
C'est à peu près la meilleure description que j'ai lue sur -exec. C'est extrêmement puissant mais j'ai toujours du mal à obtenir la bonne syntaxe. Cela a rendu certaines choses beaucoup plus claires. Emballage particulier de la commande dans un shell séparé. Agréable. Merci.
Eurospoofer

3
Notez que -andet -orne sont pas portables. POSIX spécifie -aet-o , et en fait -aest toujours supposé (donc pas nécessaire).
gniourf_gniourf

Il doit également y avoir un espace devant le terminateur. Ex "\;"ne fonctionne pas mais " \;"fonctionne
frmdstryr

56

Je 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.

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

Vous ne savez pas si la variable du fichier sera supprimée? Quelqu'un sait si c'est le cas?
Abs

7
Pour tester de telles choses, ajoutez simplement un echoavant les commandes et voyez ce qu'il fait.
Marian

2
@Marian, echoest assez peu fiable - vous ne pouvez pas faire la différence entre echo "one argument"et echo one argument(la sortie de ce dernier étant fausse, car elle passe en fait echodeux 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.
Charles Duffy

52

Essayez de mettre un espace avant chaque \;

Travaux:

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

Ne fonctionne pas:

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

1
Cela me fait monter souvent. Un de ces jours, j'ajouterai un espace par défaut.
harperville

Pour moi, cela fonctionne exactement dans Cygwin sous Windows 7: pas d'espace avant \; fonctionne, avec l'espace - ne fonctionne pas. Mais si j'enlève \, avec de l'espace avant; cela fonctionne, et sans espace avant; ce n'est pas le cas, juste comme il est décrit ici.
WebComer

7

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 {} ;


J'ai vraiment confondu. find /etc/nginx -name '*.conf' -exec echo {} ;et a find /etc/nginx -name '*.conf' -exec echo {}\;donné le même résultat. :(
Kirby

J'utilise le shell Bash fourni avec Git pour Windows, et la réponse de Dustin Cowles fonctionne pour moi. En d'autres termes: pas de guillemets, barre oblique inverse échappée par un point-virgule, espace après {}.
mamacdon

Il n'y a pas de différence de sens, mais dans certains cas, vous devez mettre la barre oblique inverse, dans certains cas, vous ne pouvez pas le mettre, et dans d'autres cas, vous pouvez choisir.
Dominique

2

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 \;

bash 'remove_wars' do
  user 'ubuntu'
  cwd '/'
  code <<-EOH
    find /home/ubuntu/wars -type f -name "*.war" -exec rm {} \\;
  EOH
  ignore_failure true
end

2

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 ";".

find <file path> -name "myFile.*" -exec rm - f {} ;

2
Le fait de ;ne pas être cité ou échappé ici signifie qu'il peut être consommé par le shell, et non lu par find. Aussi, -fet ce - fsont deux choses différentes.
Charles Duffy

1

Vous devez vous échapper, je pense.

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

0

{} Et && causeront des problèmes en raison de l'extension de la ligne de commande. Je suggère d'essayer:

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

Si la première commande dans exec réussit et la deuxième commande dans exec est exécutée, aura-t-elle toujours accès à la {}variable pour supprimer le bon fichier?
Abs

À quoi vous épilez-vous {}? Sauf s'il contient deux points ou virgules qui resteront tels quels.
Marian

0

Vous devez mettre un espace entre {}et\;

La commande sera donc comme:

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

-4

Si vous obtenez toujours "find: argument manquant à -exec", essayez de placer l'argument d'exécution entre guillemets.

find <file path> -type f -exec "chmod 664 {} \;"
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.