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è di sbagliato in questo comando, poiché sembra corrispondere alla pagina man :
-exec command {} +
Questa variante dellopzione -exec esegue il comando specificato sui file selezionati, ma la riga di comando è costruita aggiungendo alla fine ogni nome di file selezionato; il numero totale di invocazioni del comando sarà molto inferiore al numero di file corrispondenti. La riga di comando è costruita più o meno nello stesso modo in cui xargs costruisce il suo righe di comando. Nel comando è consentita una sola 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 "{}" \+
Commenti
Risposta
Cera diversi problemi con i tuoi tentativi, inclusi i backtick utilizzati al posto delle virgolette (rimossi nelle modifiche successive alla domanda), virgolette mancanti dove sono richieste, virgolette extra dove sono inutili, parentesi mancanti nel gruppo -o
clausole e diverse implementazioni di find
utilizzate (vedere i commenti e la chat per i dettagli).
Ad ogni modo, il comando può essere semplificato in questo modo:
find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} +
o, se dovessi usare una versione arcaica GNU find, dovrebbe sempre funzionare:
find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \;
Commenti
- Spiacenti, dovevano essere virgolette non backtick.
- Le virgolette sarebbero inutili come
{}
non ha alcun significato specifico per la shell. - Dalle pagine man di find: ” La stringa ‘ { } ‘ è sostituito dal nome del file corrente in fase di elaborazione ovunque si trovi negli argomenti del comando, non solo negli argomenti in cui è solo, come in alcune versioni di find. Potrebbe essere necessario eseguire lescape di entrambe queste costruzioni (con un ‘ \ ‘) o citarle per proteggerle dallespansione della shell. ”
- Lho effettivamente letto nella pagina di manuale ma il fatto è che non esiste una shell di cui ‘ sono a conoscenza che richiede la citazione delle parentesi graffe. Quale shell stai usando?
- bash. Con o senza le virgolette ricevo comunque lerrore.
Risposta
“argomento mancante per -exec
“di solito significa che largomento di – exec
manca del suo terminatore. Il terminatore deve essere un argomento contenente solo il carattere ;
(che deve essere citato in un comando della shell, quindi “è tipicamente scritto \;
o ";"
) o due argomenti successivi contenenti {}
e +
.
Stephane Chazelas ha identificato che “stai utilizzando una versione precedente di GNU che non supporta -exec … {} +
, solo -exec {} \;
.Sebbene GNU sia stato lultimo ad adottare -exec … {} +
, ti consiglio di procurarti una suite di strumenti meno antica (come Cygwin , che include git e molto altro ancora, o GNUwin32 , che manca di git ma “t ha il cattivo-impiegato-che-cerca-di-usare-linux -but-we-impose-windows vibe che Cygwin dà). Questa funzione è stata aggiunta nella versione 4.2.12, oltre 9 anni fa (era lultima funzionalità identificata per rendere GNU find
Conforme a POSIX).
Se vuoi restare fedele a una vecchia ricerca GNU, puoi usare -print0
con xargs -0
per ottenere una funzionalità simile: esecuzione di comandi raggruppati, supporto di nomi di file arbitrari.
find a/folder b/folder -name "*.c" -o -name "*.h" -print0 | xargs -0 grep -I foobar /dev/null
Cita sempre i caratteri jolly su find
riga di comando. Altrimenti, se ti capita di eseguire questo comando da una directory contenente file .c
, il *.c
non quotato woul d essere espanso nellelenco di .c
file nella directory corrente.
Aggiunta di /dev/null
a grep
la riga di comando è un trucco per garantire che grep stamperà sempre il nome del file, anche se find
trova una singola corrispondenza. Con GNU find, un altro metodo è passare lopzione -H
.
Commenti
- Cosa fai intendi per cattivo dipendente che cerca di usare Linux ma noi imponiamo latmosfera di Windows che Cygwin dà?
- GNUwin32 non ‘ non mi aspettavo 🙁
- Vedi i miei commenti sulla domanda.
- Le virgolette attorno al semi sono state elaborate allinterno di uno script package.json.
Risposta
Se un comando come
find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} +
restituisce un errore
find: missing argument to -exec
la causa probabile è troppo vecchia GNU find
che non supporta la sintassi -exec mycommand {} +
. In tal caso, la sostituzione a basso rendimento consiste nelleseguire -exec mycommand {} \;
che eseguirà mycommand
una volta per ogni target trovato invece di raccogliere più target ed eseguendo mycommand
solo una volta.
Tuttavia, GNU find
doe s non supporta ad es.
find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts +
perché GNU find
supporta solo la combinazione letterale {} +
invece di {} additional parameters +
più generico. Tieni presente che non può esserci nulla tra le parentesi graffe e il carattere +
. Se lo provi, otterrai lo stesso errore:
find: missing argument to -exec
La soluzione alternativa è utilizzare la sintassi {} additional parameters \;
che funziona ma eseguirà il comando una volta per ogni destinazione trovata. Se hai bisogno di più prestazioni con GNU find
devi scrivere uno script wrapper che possa aggiungere parametri aggiuntivi agli argomenti forniti. Qualcosa come
#!/bin/bash exec mycommand "$@" additional parameters
dovrebbe essere abbastanza buono. Oppure, se non vuoi creare un file temporaneo, puoi usare una riga per cambiare lordine 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
. Tieni presente che potresti dover raddoppiare i caratteri speciali di escape per la bash dopo il flag -c
.
Commenti
- (1) La parte di cui sopra che risponde effettivamente alla domanda era già stata data da altre persone. (2) Ciò che stai descrivendo non è un difetto o una carenza in GNU
find
, ma il comportamento corretto specificato da POSIX . - +1 Infine, qualcuno che risponde al motivo per cui parametri aggiuntivi non ‘ non funzionano! Sembra una carenza nella definizione POSIX.
- Se ‘ utilizzi GNU
find
tu ‘ probabilmente hai GNUcp
. In questo caso puoifind ... -exec cp --target-directory ~/.fonts {} +
per mantenere{}
alla fine della stringa di esecuzione.
Risposta
find . -type f -perm 0777 -exec chmod 644 {}\;
ha ricevuto errore find: missing argument to ``-exec"
.
Laggiunta di spazio tra {}
e \
ha risolto il problema:
find . -type f -perm 0777 -print -exec chmod 644 {} \;
Commenti
- Non è presente alcun problema di questo tipo nel
find
comando nella domanda in questione. - In Domanda non è, va bene, che ho capito, ma il problema è lo stesso ” trova: argomento mancante a “ -exec ‘ “, Il problema può essere dovuto a 2 motivi diversi, ho risposto perché ho visto la stessa dichiarazione del problema.
- @Kusalananda good grief, il noob ha fornito una soluzione per lerrore segnalato che è dichiarato dallOP sia nel titolo che nel corpo della domanda.
- @bvj La domanda tratta esplicitamente con la forma
+
dellopzione-exec
perfind
. Questa risposta corregge un problema che lutente che pone la domanda non ha.
Risposta
Ho avuto il mio quota di mal di testa con la sintassi exec in passato. quasi tutti i giorni ora preferisco la sintassi bash più carina:
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 modo seriale, ma puoi reindirizzare loutput altrove benissimo
Commenti
- Anche se tende a funzionare, è significativamente meno utile della versione pure-find perché non può gestire correttamente i file con spazi bianchi nel nome.
- No, non ‘ farlo. Questo si interrompe non appena i file contengono spazi e altri caratteri “strani”. Questo è anche più complesso e più lento di
find … -exec … \;
, quindi ‘ non cè motivo di usarlo anche se sai che i nomi dei tuoi file sono tame. - questo è stato utile per la mia situazione in cui avevo bisogno di eseguire più righe di logica in base ai nomi dei file (come rimuovere i caratteri, creare directory e quindi spostare i file). Cercare di trovare per fare più cose in una
exec
è stato un gran mal di testa per i 5 minuti che volevo dedicare a questo. I miei nomi di file erano docili e questo ha risolto il mio problema 🙂
+
alla fine?find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
find
. Sebbene la variante-exec cmd {} +
sia POSIX ed è disponibile dagli anni 80, GNU lha aggiunta solo (relativamente) di recente (2005). Cosa ti dicefind --version
?-exec {} +
è stato aggiunto nella 4.2.12 nel 2005. Nelle vecchie scoperte GNU, puoi utilizzare-print0 | xargs -r0
(non POSIX) per ottenere qualcosa simile.4.1
è del 1994.-name
pattern gli argomenti devono essere tra virgolette:-name "*.c" -o -name "*.h"
. Questo è vero, sebbene non sia correlato allerrore-exec
. Noterai che tutte le altre risposte mettono i caratteri jolly tra virgolette, anche se solo Gilles lo menziona. … (Continua)-name "*.[ch]"
senza spiegazione. Questo ha i vantaggi di semplificare la riga di comando e, in particolare, di eliminare-o
. Trovare espressioni che coinvolgono-o
sono difficili da ottenere correttamente. Il tuo è sbagliato; se il tuo comando è corretto in modo che non vada in errore (come nella risposta di Gilles), verrà eseguitogrep
solo su.h
File. Devi fare'(' -name '*.c' -o -name '*.h' ')'
.