Î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

  • Ați încercat să scăpați de + la final? find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
  • Este posibil să utilizați o versiune veche a GNU 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ă spune find --version?
  • @Koveras, asta ar fi atunci. -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.
  • JRFerguson a subliniat (într-un răspuns care a fost șters) că modelul -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)
  • (Continuare) … răspunsul lui jlliagre restrânge expresia numelui la -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 rula grep numai pe .h fișiere. Trebuie să faceți '(' -name '*.c' -o -name '*.h' ')'.

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 GNU cp. În acest caz, puteți find ... -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 la find. 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 🙂

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *