trova: argomento mancante per -exec


18

Sto cercando di eseguire il seguente comando:

find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' +

Questo sta restituendo un errore:

find: missing argument to -exec

Non riesco a vedere cosa c'è che non va in questo comando, poiché sembra corrispondere alla pagina man:

-exec comando {} +

Questa variante dell'opzione -exec esegue il comando specificato sui file selezionati, ma la riga di comando viene creata aggiungendo alla fine ciascun nome di file selezionato; il numero totale di invocazioni del comando sarà molto inferiore al numero di file corrispondenti. La riga di comando è costruita nello stesso modo in cui xargs costruisce le sue righe di comando. Nel comando è consentita solo un'istanza di '{}'. Il comando viene eseguito nella directory iniziale.

Ho anche provato:

find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar {} +
find a/folder b/folder -name *.c -o -name *.h -exec 'grep -I foobar' {} +
find a/folder b/folder -name *.c -o -name *.h -exec 'grep -I foobar' '{}' +
find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar '{}' +
find a/folder b/folder \( -name *.c -o -name *.h \) -exec grep -I foobar '{}' +
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+

Hai provato a scappare +alla fine? find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
Jayhendren,

3
È possibile che tu stia utilizzando una vecchia versione di GNU find. Sebbene la -exec cmd {} +variante sia POSIX ed è disponibile dagli anni '80, GNU la trova aggiunta (relativamente) di recente (2005). Che cosa find --versionti dice?
Stéphane Chazelas,

2
@Koveras, sarebbe allora. -exec {} +è stato aggiunto in 4.2.12 nel 2005. Nei precedenti risultati GNU, è possibile utilizzare (non POSIX) -print0 | xargs -r0per ottenere qualcosa di simile. 4.1è del 1994.
Stéphane Chazelas,

1
JRFerguson sottolineato (in una risposta che è stato eliminato) che gli -nameargomenti del modello dovrebbero essere citati: -name "*.c" -o -name "*.h". Questo è vero, anche se non è correlato -execall'errore. Noterai che tutte le altre risposte mettono i caratteri jolly tra virgolette, anche se solo Gilles lo menziona. ... (proseguendo)
G-Man dice "Ripristina Monica" il

1
(Proseguendo) ... la risposta di jlliagre fa crollare l'espressione del nome -name "*.[ch]"senza spiegazioni. Ciò ha i vantaggi di semplificare la riga di comando e, in particolare, di eliminare  -o. Trova espressioni che coinvolgono -oè difficile da ottenere. Il tuo è sbagliato; se il tuo comando è risolto in modo tale da non sbagliare (come nella risposta di Gilles), verrà eseguito grepsolo sui .hfile. Hai bisogno di fare '(' -name '*.c' -o -name '*.h' ')'.
G-Man dice "Ripristina Monica" il

Risposte:


18

Devi rimuovere le virgolette singole che usi in giro {}. Il comando può essere semplificato in questo modo:

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} +

Se si utilizza una versione di ricerca GNU arcaica, questo dovrebbe comunque funzionare:

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \;

Oops, dovevano essere citazioni e non contraccolpi.
David Kennedy,

Le citazioni sarebbero inutili in quanto {}non hanno un significato specifico per la shell.
jlliagre,

Dalle pagine man di find: "La stringa '{}' è sostituita dal nome del file corrente che viene elaborato ovunque si presenti negli argomenti al comando, non solo negli argomenti in cui è solo, come in alcune versioni di find. Entrambi potrebbe essere necessario sfuggire alle costruzioni (con un '\') o quotarle per proteggerle dall'espansione della shell. "
David Kennedy

1
In effetti l'ho letto nella pagina del manuale, ma il fatto è che non ci sono shell di cui sono a conoscenza e che richiede la citazione delle parentesi graffe. Che shell stai usando?
jlliagre,

bash. Con o senza le virgolette ricevo comunque l'errore.
David Kennedy,

10

"Argomento mancante a -exec" di solito significa che l'argomento a - execmanca il suo terminatore. Il terminatore deve essere un argomento contenente solo il carattere ;(che deve essere citato in un comando di shell, quindi in genere è scritto \;o ';') oppure due argomenti successivi contenenti {}e +.

Stephane Chazelas ha identificato che stai usando una versione precedente di GNU find che non supporta -exec … {} +, solo -exec {} \;. Sebbene GNU sia stato un tardivo ad adottare -exec … {} +, ti consiglio di ottenere una suite di strumenti meno antica (come Cygwin , che include git e molto altro ancora, o GNUwin32 , che manca di git ma non ha i tentativi dei cattivi dipendenti -per-usare-linux-ma-imponiamo-l'atmosfera di Windows che dà Cygwin). Questa funzione è stata aggiunta nella versione 4.2.12, oltre 9 anni fa (è stata l'ultima funzionalità identificata a rendere findcompatibile GNU POSIX).

Se si desidera attenersi a una ricerca GNU precedente, è possibile utilizzare -print0con xargs -0per ottenere una funzionalità simile: esecuzione di comandi raggruppati, che supporta nomi di file arbitrari.

find a/folder b/folder -name '*.c' -o -name '*.h' -print0 | xargs -0 grep -I foobar /dev/null

Citare sempre i caratteri jolly nella findriga di comando. Altrimenti, se ti capita di eseguire questo comando da una directory contenente .cfile, il non quotato *.cverrebbe espanso all'elenco dei .cfile nella directory corrente.

L'aggiunta /dev/nullalla grepriga di comando è un trucco per garantire che grep stamperà sempre il nome del file, anche se findtrova una singola corrispondenza. Con GNU find, un altro metodo è passare l'opzione -H.


1
Cosa intendi per atmosfera da cattivo-dipendente-che-cerca-di-usare-linux-ma-noi-imponiamo-windows che dà cygwin?
David Kennedy,

GNUwin32 non si aspettava :(
David Kennedy,

Vedi i miei commenti sulla domanda.
G-Man dice "Ripristina Monica" il

Le virgolette intorno alla semi hanno funzionato all'interno di uno script package.json.
bvj,

2

Se un comando come

find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} +

restituisce errore

find: missing argument to -exec

la causa probabile è GNU troppo vecchia findche non supporta la sintassi -exec mycommand {} +. In tal caso, -exec mycommand {} \;verrà eseguita la sostituzione a basse prestazioni che eseguirà mycommanduna volta per ogni destinazione trovata invece di raccogliere più destinazioni ed eseguire la mycommandsola volta.

Tuttavia, GNU findnon supporta ad es

find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts +

perché GNU findsupporta solo una combinazione letterale {} +anziché più generica {} additional parameters +. Nota che non ci può essere nulla tra le parentesi graffe e il +personaggio. Se provi questo, otterrai lo stesso errore:

find: missing argument to -exec

La soluzione alternativa consiste nell'utilizzare la sintassi {} additional parameters \;che funziona ma eseguirà il comando una volta per ogni destinazione trovata. Se hai bisogno di maggiori prestazioni con GNU finddevi scrivere uno script wrapper in grado di aggiungere parametri aggiuntivi agli argomenti forniti. Qualcosa di simile a

#!/bin/bash
exec mycommand "$@" additional parameters

dovrebbe essere abbastanza buono. Oppure, se non si desidera creare un file temporaneo, è possibile utilizzare una riga per modificare l'ordine dei parametri in questo modo:

find . -type f -and -name "*.ttf" -exec bash -c 'mycommand "$@" extra arguments' {} +

che eseguirà mycommand {list of ttf files} extra arguments. Nota che potresti dover scappare due caratteri speciali per il bash dopo la -cbandiera.


(1) La parte di cui sopra che risponde effettivamente alla domanda è già stata data da altre persone. (2) Quello che stai descrivendo non è un difetto o un difetto di GNU find, ma il comportamento corretto specificato da POSIX .
G-Man dice "Ripristina Monica" il

1
+1 Infine, qualcuno che risponde al motivo per cui parametri aggiuntivi non funzionano! Sembra una carenza nella definizione POSIX.
Jonathan,

Se hai GNU findprobabilmente hai GNU cp. In questo caso è possibile find ... -exec cp --target-directory ~/.fonts {} +mantenere {}la fine della stringa di esecuzione.
roaima,

1

find . -type f -perm 0777 -exec chmod 644 {}\;

ho ricevuto un errore find: missing argument to ``-exec'.

Aggiungendo spazio tra {}e \riparato:

find . -type f -perm 0777 -print -exec chmod 644 {} \;


1
Non esiste tale problema nel findcomando nella domanda a portata di mano.
Kusalananda

In questione non ho capito bene, ma il problema è lo stesso "trova: argomento mancante a` `-exec '", il problema può verificarsi per ragioni diverse-2, ho risposto perché ho visto la stessa dichiarazione di problema.
ShreePool

@Kusalananda buon dolore, il noob ha fornito una soluzione per l'errore segnalato che è dichiarato dall'OP nel titolo e nel corpo della domanda.
bvj

@bvj La domanda si occupa esplicitamente della +forma -execdell'opzione per find. Questa risposta corregge un problema che l'utente che pone la domanda non ha.
Kusalananda

-1

Ho avuto la mia parte di mal di testa con la sintassi exec in passato. quasi tutti i giorni preferisco la migliore sintassi bash:

for f in `find a/folder b/folder -name "*.[ch]"`; do grep -I foobar $f; done

Presenta alcune limitazioni quando si desidera trattare i file come un gruppo, poiché ciascuno viene valutato in serie, ma è possibile reindirizzare l'output altrove


1
Mentre questo tende a funzionare, è significativamente meno utile della versione pure-find perché non può gestire correttamente i file con spazi bianchi nel nome.
Etan Reisner

5
No, non farlo. Questo si interrompe non appena i file contengono spazi e altri caratteri "strani". Anche questo è più complesso e più lento di find … -exec … \;, quindi non c'è motivo di usarlo anche se sai che i nomi dei tuoi file sono mansueti.
Gilles 'SO- smetti di essere malvagio'

questo è stato utile per la mia situazione in cui avevo bisogno di eseguire più linee di logica basate sui nomi dei file (come rimuovere i caratteri, creare directory e quindi spostare i file). Cercare di scoprire di fare più cose in una è execstato un vero mal di testa per i 5 minuti che volevo spendere per questo. I nomi dei miei file erano docili e questo ha risolto il mio problema :)
gMale
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.