trova: argomento mancante per -exec


206

Sono stato aiutato oggi con un comando, ma non sembra funzionare. Questo è il comando:

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

La shell ritorna

find: missing argument to `-exec'

Quello che sto sostanzialmente cercando di fare è passare ricorsivamente in una directory (se ha altre directory) ed eseguire il comando ffmpeg sui .rmtipi di file e convertirli in .mp3tipi di file. Fatto ciò, rimuovere il .rmfile che è appena stato convertito.

Apprezzo qualsiasi aiuto in merito.

Risposte:


340

Un -execcomando deve essere terminato con un ;(quindi di solito è necessario digitare \;o ';'per evitare l'interpretazione da parte della shell) o un +. La differenza è che con ;, il comando viene chiamato una volta per file, con +, viene chiamato il minor numero di volte possibile (di solito una volta, ma esiste una lunghezza massima per una riga di comando, quindi potrebbe essere suddiviso) con tutti i nomi di file . Vedi questo esempio:

$ 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

Il tuo comando ha due errori:

In primo luogo, si utilizza {};, ma ;deve essere un parametro a sé stante.

In secondo luogo, il comando termina in &&. Hai specificato "run find, e se ciò ha avuto successo, rimuovi il file chiamato {};.". Se si desidera utilizzare roba di shell nel -execcomando, è necessario eseguirla esplicitamente in una shell, ad esempio -exec sh -c 'ffmpeg ... && rm'.

Comunque non dovresti aggiungere {} all'interno del comando bash, produrrà problemi quando ci sono caratteri speciali. Invece, puoi passare parametri aggiuntivi alla shell dopo -c command_string(vedi man sh):

$ ls
$(echo damn.)
$ find * -exec sh -c 'echo "{}"' \;
damn.
$ find * -exec sh -c 'echo "$1"' - {} \;
$(echo damn.)

Vedi la $cosa viene valutata dalla shell nel primo esempio. Immagina che ci fosse un file chiamato $(rm -rf /):-)

(Nota a margine: -non è necessario, ma la prima variabile dopo il comando è assegnata alla variabile $0, che è una variabile speciale che normalmente contiene il nome del programma in esecuzione e l'impostazione su un parametro è un po 'sporca, anche se ha vinto probabilmente causerà qualche danno qui, quindi lo impostiamo su giusto -e per cominciare $1.)

Quindi il tuo comando potrebbe essere qualcosa di simile

find -exec bash -c 'ffmpeg -i "$1" -sameq "$1".mp3 && rm "$1".mp3' - {} \;

Ma c'è un modo migliore. trovare supporti ande or, quindi, puoi fare cose come find -name foo -or -name bar. Ma funziona anche con -exec, che valuta vero se il comando termina correttamente e falso in caso contrario. Vedi questo esempio:

$ ls
false  true
$ find * -exec {} \; -and -print
true

Esegue la stampa solo se il comando è stato eseguito correttamente, cosa che ha fatto per truema non per false.

Quindi puoi usare due istruzioni exec concatenate con an -and, e eseguirà quest'ultima solo se la prima è stata eseguita con successo.


3
La chiave sembra essere la linea di Marian di "il; è un argomento a parte" che è quello che ha fatto per me, saggia lampadina e per il mio esempio di codice. Grazie.
Pjammer,

3
Questa è la migliore descrizione che ho letto su -exec. È estremamente potente ma trovo sempre difficile ottenere la sintassi giusta per questo. Questo ha reso alcune cose molto più chiare. In particolare avvolgendo il comando nella shell separata. Bello. Grazie.
Eurospoofer,

3
Si noti che -ande -ornon sono portatili. POSIX specifica -ae-o , di fatto, -aviene sempre assunto (quindi non necessario).
gniourf_gniourf

Inoltre, deve essere presente uno spazio prima del terminatore. Ex "\;"non funziona ma " \;"funziona
frmdstryr

56

L'ho capito ora. Quando è necessario eseguire due comandi in exec in una ricerca, è necessario disporre effettivamente di due exec separati. Questo alla fine ha funzionato per me.

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

Non sei sicuro se riuscirà a eliminare la variabile del file? Qualcuno sa se questo è il caso?
Abs

7
Per provare queste cose basta aggiungere un echoprima dei comandi e vedere cosa fa.
Marian,

2
@Marian, echoè abbastanza inaffidabile - non puoi dire la differenza tra echo "one argument"e echo one argument(l'output di quest'ultimo è falso, dato che in realtà sta passando echodue argomenti completamente separati). Molto meglio fare qualcosa del genere -exec bash -c 'printf "%q " "$@"' _ ffmpeg -i {} -sameq {}.mp3 \; -printf '\n', che stamperà l'output in modo da rendere visibili i caratteri non stampabili in modo da poter rilevare nuove righe DOS e altre stranezze.
Charles Duffy,

52

Prova a mettere uno spazio prima di ogni \;

Lavori:

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

Non funziona:

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

1
Questo mi fa inciampare abbastanza spesso. Uno di questi giorni, aggiungerò uno spazio per impostazione predefinita.
Harperville,

Per me funziona esattamente l'opposto in Cygwin in Windows 7: nessuno spazio prima di \; funziona, con spazio - no. Ma se rimuovo \, con spazio prima; funziona e senza spazio prima; non lo è, proprio come descritto qui.
WebComer

7

Per vostra informazione:
ho appena provato a usare il comando "trova -exec" su un sistema Cygwin (UNIX emulato su Windows), e lì sembra che la barra rovesciata prima del punto e virgola debba essere rimossa:
find ./ -name "blabla" -exec wc -l {} ;


Sono davvero confuso. find /etc/nginx -name '*.conf' -exec echo {} ;e ha find /etc/nginx -name '*.conf' -exec echo {}\;dato lo stesso risultato. :(
Kirby

Sto eseguendo la shell Bash fornita con Git per Windows e la risposta di Dustin Cowles funziona per me. In altre parole: senza virgolette, barra rovesciata sfuggita al punto e virgola, spazio dopo {}.
mamacdon,

Non c'è differenza nel significato, ma in alcuni casi è necessario inserire la barra rovesciata, in alcuni casi non è possibile inserirla, e in altri casi è possibile scegliere.
Dominique,

2

Nel caso in cui qualcuno veda un simile "Argomento -exec mancante" negli script bash di Amazon Opsworks Chef, ho dovuto aggiungere un'altra barra rovesciata per sfuggire a \;

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

Inoltre, se qualcun altro ha l'argomento "trova: manca a -exec" questo potrebbe aiutare:

In alcune shell non è necessario eseguire l'escaping, ovvero non è necessario il "\" davanti al ";".

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

2
Il ;non essere citato o sfuggito qui significa che può essere consumato dalla shell, non letto da find. Inoltre, -fe - fsono due cose diverse.
Charles Duffy,

1

Dovresti scappare, credo.

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

0

Sia {} che && causeranno problemi a causa dell'espansione dalla riga di comando. Suggerirei di provare:

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

Se il primo comando in exec ha esito positivo e viene eseguito il secondo comando in exec, avrà comunque accesso alla {}variabile per eliminare il file giusto?
Abs

In cosa si {}espande Thinik ? A meno che non contenga due punti o virgole che rimarranno così come sono.
Marian,

0

Devi mettere uno spazio tra {}e\;

Quindi il comando sarà come:

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

-4

Se stai ancora ottenendo "trova: argomento mancante per -exec" prova a racchiudere l'argomento execute tra virgolette.

find <file path> -type f -exec "chmod 664 {} \;"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.