Încerc să rulez următoarea comandă:
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar "{}" +
Aceasta returnează o eroare:
find: missing argument to -exec
Nu pot să văd ce nu este în regulă cu această comandă, deoarece pare să se potrivească cu pagina de manual :
-exec comanda {} +
Această variantă a opțiunii -exec rulează comanda specificată pe fișierele selectate, dar linia de comandă este construită prin adăugarea fiecărui nume de fișier selectat la final; numărul total de invocații ale comenzii va fi mult mai mic decât numărul de fișiere potrivite. Linia de comandă este construită în același mod în care xargs își construiește linii de comandă. Este permisă o singură instanță de „{}” în cadrul comenzii. Comanda este executată în directorul de pornire.
De asemenea, am încercat:
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 "{}" \+
Comentarii
Răspuns
A existat mai multe probleme cu încercările dvs., inclusiv backticks-urile folosite în loc de ghilimele (eliminate în editări ulterioare la întrebare), ghilimele lipsă acolo unde sunt necesare, ghilimele suplimentare unde sunt inutile, lipsesc parantezele pentru gruparea -o
clauze și diferite implementări ale find
utilizate (consultați comentariile și chatul pentru detalii).
Oricum, comanda poate fi simplificată astfel:
find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} +
sau, dacă utilizați o versiune arhaică GNU, aceasta ar trebui să funcționeze întotdeauna:
find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \;
Comentarii
- Hopa, au fost menite să fie ghilimele, nu backticks.
- Cotațiile ar fi inutile ca
{}
nu are nicio semnificație specifică pentru shell. - Din paginile de căutare: ” Șirul ‘ { } ‘ este înlocuit de numele fișierului curent procesat peste tot apare în argumentele la comandă, nu doar în argumentele în care este singur, ca în unele versiuni de find. Este posibil ca ambele construcții să fie evitate (cu un ‘ \ ‘) sau citate pentru a le proteja de expansiunea de către shell. ”
- Într-adevăr, am citit asta în pagina manualului, dar adevărul este că nu există niciun shell care să știe ‘ care necesită citarea acoladelor. Ce shell folosiți?
- bash. Cu sau fără ghilimele am primit eroarea oricum.
Răspuns
„argument lipsă la ”înseamnă de obicei că argumentului pentru – exec
îi lipsește terminatorul. Terminatorul trebuie să fie fie un argument care să conțină doar caracterul ;
(care trebuie să fie citat într-o comandă shell, deci este de obicei scris \;
sau ";"
), sau două argumente succesive care conțin {}
și +
.
Stephane Chazelas a identificat că utilizați o versiune mai veche de găsire GNU care nu acceptă -exec … {} +
, numai -exec {} \;
.Deși GNU a adoptat târziu -exec … {} +
, vă recomand să obțineți o suită de instrumente mai puțin antică (cum ar fi Cygwin , care include git și multe altele, sau GNUwin32 , căruia îi lipsește git, dar nu are programul rău-angajat-care-încearcă-să-folosească-Linux -but-we-impose-windows vibe pe care Cygwin o oferă). Această caracteristică a fost adăugată în versiunea 4.2.12, cu peste 9 ani în urmă (a fost ultima caracteristică identificată care a creat GNU find
Compatibil POSIX).
Dacă doriți să rămâneți la o căutare GNU mai veche, puteți utiliza -print0
cu xargs -0
pentru a obține o funcționalitate similară: executarea comenzilor grupate, care acceptă nume de fișiere arbitrare.
find a/folder b/folder -name "*.c" -o -name "*.h" -print0 | xargs -0 grep -I foobar /dev/null
Citați întotdeauna caracterele comodă pe find
linia de comandă. În caz contrar, dacă se întâmplă să executați această comandă dintr-un director care conține fișiere .c
, *.c
nu va fi citat d să fie extins la lista de fișiere .c
din directorul curent.
Adăugarea /dev/null
la grep
linia de comandă este un truc pentru a vă asigura că grep va imprima întotdeauna numele fișierului, chiar dacă find
găsește o singură potrivire. Cu GNU find, o altă metodă este să treceți opțiunea -H
.
Comentarii
- Ce faceți Înțelegeți prin rău-angajat-încercarea-de-a-folosi-linux-dar-impunem-windows vibe pe care Cygwin o dă?
- GNUwin32 nu are ‘ 🙁
- Vedeți comentariile mele la întrebare.
- Citatele din jurul semifuncționalului au funcționat dintr-un script package.json.
Răspuns
Dacă o comandă precum
find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} +
returnează eroarea
find: missing argument to -exec
cauza probabilă este prea veche GNU find
care nu acceptă sintaxa -exec mycommand {} +
. În acest caz, înlocuirea performanței scăzute este de a rula -exec mycommand {} \;
care va rula mycommand
o dată pentru fiecare țintă găsită în loc să colecteze mai multe ținte și rularea mycommand
o singură dată.
Cu toate acestea, GNU find
doe nu acceptă de ex.
find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts +
deoarece GNU find
acceptă numai combinația literală {} +
în loc de mai generic {} additional parameters +
. Rețineți că nu poate exista nimic între paranteze și caracterul +
. Dacă încercați acest lucru, veți primi aceeași eroare:
find: missing argument to -exec
Soluția este să utilizați sintaxa {} additional parameters \;
care funcționează, dar va executa comanda o dată pentru fiecare țintă găsită. Dacă aveți nevoie de mai multă performanță cu GNU find
trebuie să scrieți un script de împachetare care poate adăuga parametri suplimentari la argumentele date. Ceva ca
#!/bin/bash exec mycommand "$@" additional parameters
ar trebui să fie suficient de bun. Sau, dacă nu doriți să creați fișier temporar, puteți utiliza un singur liner pentru a schimba ordinea parametrilor ca aceasta:
find . -type f -and -name "*.ttf" -exec bash -c "mycommand "$@" extra arguments" {} +
care va executa mycommand {list of ttf files} extra arguments
. Rețineți că poate fi necesar să evadați dublu caractere speciale pentru bash după semnalizatorul -c
.
Comentarii
- (1) Partea din cele de mai sus care răspunde efectiv la întrebare a fost deja dată de alte persoane. (2) Ceea ce descrieți nu este un defect sau o deficiență în GNU
find
, ci comportamentul corect specificat de POSIX . - +1 În sfârșit, cineva care răspunde de ce parametrii suplimentari nu funcționează ‘! Pare o deficiență în definiția POSIX.
- Dacă ‘ veți GNU
find
veți ‘ probabil că am primit GNUcp
. În acest caz, putețifind ... -exec cp --target-directory ~/.fonts {} +
să păstrați{}
la sfârșitul șirului de execuție.
Răspuns
find . -type f -perm 0777 -exec chmod 644 {}\;
a apărut o eroare find: missing argument to ``-exec"
.
Adăugarea spațiului între {}
și \
a remediat-o:
find . -type f -perm 0777 -print -exec chmod 644 {} \;
Comentarii
- Nu există o astfel de problemă în
find
comanda din întrebarea la îndemână. - În întrebare nu am înțeles bine, dar problema este aceeași ” find: argument lipsă la `-exec ‘ „, problema poate apărea dintr-un motiv diferit-2, am răspuns pentru că am văzut aceeași declarație de problemă.
- @Kusalananda durere bună, noob a oferit o soluție pentru eroarea raportată, care este menționată de PO atât în titlul, cât și în corpul întrebării.
- @bvj Întrebarea se referă în mod explicit cu formularul
+
al opțiunii-exec
lafind
. Acest răspuns corectează o problemă pe care utilizatorul care pune întrebarea nu o are.
Răspuns
Am avut ponderea durerilor de cap cu sintaxa exec în trecut. acum majoritatea zilelor prefer sintaxa bash mai frumoasă:
for f in `find a/folder b/folder -name "*.[ch]"`; do grep -I foobar $f; done
Are unele limitări atunci când doriți să tratați fișierele ca un grup, deoarece fiecare este evaluat în serie, dar puteți transmite ieșirea în altă parte foarte bine
Comentarii
- Deși acest lucru tinde să funcționeze, acesta este semnificativ mai puțin util decât versiunea de căutare pură, deoarece nu poate gestiona corect fișierele cu spațiu alb în nume.
- Nu, nu ‘ nu faceți acest lucru. Aceasta se întrerupe de îndată ce fișierele conțin spații și alte caractere „ciudate”. Acest lucru este, de asemenea, mai complex și mai lent decât
find … -exec … \;
, deci nu există ‘ niciun motiv pentru a utiliza acest lucru chiar dacă știți că numele fișierelor dvs. sunt - acest lucru a fost util pentru situația mea în care trebuia să rulez mai multe linii de logică bazate pe numele fișierelor (cum ar fi eliminarea caracterelor, crearea de directoare și apoi mutarea fișierelor). Încercarea de a obține găsirea de a face mai multe lucruri într-un singur
exec
a fost o durere de cap prea mare pentru cele 5 minute pe care am vrut să le petrec în acest sens. Numele mele de fișiere au fost blânde și acest lucru a rezolvat problema mea 🙂
+
la final?find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
find
. Deși varianta-exec cmd {} +
este POSIX și este disponibilă din anii 80, GNU find a adăugat-o doar (relativ) recent (2005). Ce vă spunefind --version
?-exec {} +
a fost adăugat în 4.2.12 în 2005. În descoperirile GNU mai vechi, puteți utiliza (non-POSIX)-print0 | xargs -r0
pentru a obține ceva similar.4.1
este din 1994.-name
argumentele ar trebui citate:-name "*.c" -o -name "*.h"
. Acest lucru este adevărat, deși nu are legătură cu eroarea-exec
. Veți observa că toate celelalte răspunsuri pun comodinele în ghilimele, deși doar Gilles menționează acest lucru. … (Continuare)-name "*.[ch]"
fără explicații. Acest lucru are avantajele simplificării liniei de comandă și, în mod specific, eliminării-o
. Găsiți expresii care implică-o
sunt greu de corectat. A ta este greșită; dacă comanda dvs. este fixată astfel încât să nu se eroreze (ca în răspunsul lui Gilles), va rulagrep
numai pe.h
fișiere. Trebuie să faceți'(' -name '*.c' -o -name '*.h' ')'
.