Jag försöker köra följande kommando:

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

Detta returnerar ett fel:

find: missing argument to -exec 

Jag kan inte se vad som är fel med det här kommandot, eftersom det verkar matcha mansidan :

-exec-kommando {} +

Denna variant av alternativet -exec kör det angivna kommandot på de valda filerna, men kommandoraden byggs genom att lägga till varje valt filnamn i slutet; det totala antalet anrop på kommandot kommer att vara mycket mindre än antalet matchade filer. Kommandoraden är byggd på ungefär samma sätt som xargs bygger sin kommandorader. Endast en instans av ”{}” är tillåten i kommandot. Kommandot körs i startkatalogen.

Jag försökte också:

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 "{}" \+ 

Kommentarer

  • Har du försökt att undkomma + i slutet? find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
  • Du kanske använder en gammal version av GNU find. Även om -exec cmd {} + -varianten är POSIX och har funnits sedan 80-talet, har GNU bara lagt till den (relativt) nyligen (2005). Vad säger find --version?
  • @Koveras, det skulle då vara det. -exec {} + lades till 4.2.12 2005. I äldre GNU-fynd kan du använda (icke-POSIX) -print0 | xargs -r0 för att få något liknande. 4.1 är från 1994.
  • JRFerguson påpekade (i ett svar som har tagits bort) att -name -mönstret argument bör citeras: -name "*.c" -o -name "*.h". Detta är sant, även om det inte är relaterat till -exec -felet. Du kommer att märka att alla andra svar sätter jokertecken i citat, även om bara Gilles nämner det. … (forts.)
  • (forts.) … jlliagres svar kollapsar namnuttrycket till -name "*.[ch]" utan förklaring. Detta har fördelarna med att förenkla kommandoraden och specifikt eliminera -o. Det är svårt att hitta rätt uttryck som involverar -o. Din är fel; om ditt kommando är fixat så att det inte går fel (som i Gilles svar) körs det grep endast på .h filer. Du måste göra '(' -name '*.c' -o -name '*.h' ')'.

Svar

Det fanns flera problem med dina försök, inklusive backticks som används istället för citat (borttagna i senare ändringar av frågan), saknade citat där de krävs, extra citat där de är värdelösa, saknade parenteser till grupp -o klausuler och olika implementeringar av find används (se kommentarer och chatt för mer information).

Hur som helst kan kommandot förenklas så här:

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

eller, om du använder en arkaisk GNU-sökversion, ska detta alltid fungera:

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

Kommentarer

  • Oj, de var tänkt att vara citat inte backticks.
  • Citat skulle vara värdelösa eftersom {} har ingen specifik betydelse för skalet.
  • Från hitta man-sidor: ” Strängen ’ { } ’ är ersatt av det aktuella filnamnet som behandlas överallt i argumenten till kommandot, inte bara i argument där det är ensamt, som i vissa versioner av find. Båda dessa konstruktioner kan behöva undvikas (med en ’ \ ’) eller citeras för att skydda dem från expansion av skalet. ”
  • Jag läste verkligen det på manualsidan men faktum är att det inte finns något skal jag ’ är medveten om det kräver att citera de lockiga hängslen. Vilket skal använder du?
  • bash. Med eller utan citaten får jag ändå felet.

Svar

“saknas argument till -exec ”betyder vanligtvis att argumentet till – exec saknar sin terminator. Avslutaren måste antingen vara ett argument som bara innehåller tecknet ; (som måste citeras i ett skalkommando, så det skrivs vanligtvis \; eller ";"), eller två på varandra följande argument som innehåller {} och +.

Stephane Chazelas har identifierat att du använder en äldre version av GNU-sökning som inte stöder -exec … {} +, endast -exec {} \;.Även om GNU var en sen antagare av -exec … {} +, rekommenderar jag att du får en mindre antik verktygssvit (som Cygwin , som inkluderar git och mycket mer, eller GNUwin32 , som saknar git men inte har den dåliga medarbetaren som försöker använda Linux -but-we-impose-windows vibe som Cygwin ger). Den här funktionen lades till i version 4.2.12 för över 9 år sedan (det var den sist identifierade funktionen som gjorde GNU find POSIX-kompatibel).

Om du vill hålla dig till en äldre GNU-sökning kan du använda -print0 med xargs -0 för att få en liknande funktion: grupperad kommandokörning, stöd för godtyckliga filnamn.

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

Citera alltid jokertecken på find kommandorad. Annars, om du råkar köra det här kommandot från en katalog som innehåller .c -filer, är den ociterade *.c woul d utökas till listan över .c filer i den aktuella katalogen.

Lägg till /dev/null till grep kommandoraden är ett trick för att säkerställa att grep alltid skriver ut filnamnet, även om find råkar hitta en enstaka matchning. Med GNU-sökning är en annan metod att skicka alternativet -H.

Kommentarer

  • Vad gör du menar med dålig anställd-försöker-använda-Linux-men-vi-inför-windows-vibe som cygwin ger?
  • GNUwin32 har inte ’ t förväntar sig 🙁
  • Se mina kommentarer till frågan.
  • Citaten runt semi arbetade inifrån ett package.json-skript.

Svar

Om ett kommando som

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

returnerar fel

find: missing argument to -exec 

den troliga orsaken är för gammal GNU find som inte stöder syntax -exec mycommand {} + I så fall är ersättning med låg prestanda att köra -exec mycommand {} \; som kör mycommand en gång för varje hittat mål istället för att samla flera mål och kör mycommand bara en gång.

GNU find doe stöder inte t.ex.

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

eftersom GNU find stöder endast bokstavlig kombination {} + istället för mer generisk {} additional parameters +. Observera att det inte kan finnas något mellan hängslen och + -tecknet. Om du försöker detta får du samma fel:

find: missing argument to -exec 

Lösningen är att använda syntax {} additional parameters \; fungerar men kommer att utföra kommandot en gång för varje hittat mål. Om du behöver mer prestanda med GNU find måste du skriva ett omslagsskript som kan lägga till ytterligare parametrar till de angivna argumenten. Något som

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

borde vara tillräckligt bra. Eller, om du inte vill skapa tillfällig fil, kan du använda en-liner för att ändra ordning på parametrar så här:

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

som kommer att köras mycommand {list of ttf files} extra arguments. Observera att du kan behöva dubbla undan specialtecken för bash efter -c flaggan.

Kommentarer

  • (1) Den del av ovanstående som faktiskt svarar på frågan gavs redan av andra människor. (2) Det du beskriver är inte en brist eller brist i GNU find, men det korrekta beteendet som anges av POSIX .
  • +1 Slutligen, någon som svarar varför ytterligare parametrar inte fungerar ’ t! Det verkar som en brist i POSIX-definitionen.
  • Om du ’ har GNU find du ’ har förmodligen fått GNU cp. I det här fallet kan du find ... -exec cp --target-directory ~/.fonts {} + för att behålla {} i slutet av körsträngen.

Svar

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

fick fel find: missing argument to ``-exec".

Lägga till mellanrum mellan {} och \ fixade det:

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

Kommentarer

  • Det finns inget sådant problem i find -kommandot i frågan till hands.
  • I fråga är det inte bra, jag förstod det, men problemet är samma ” hitta: saknas argument till ” -exec ’ ”, Problem kan uppstå av olika-2 anledningar, svarade jag för att jag såg samma problemuttalande.
  • @Kusalananda god sorg, nooben gav en lösning för det rapporterade felet som anges av OP i både rubriken och huvuddelen av frågan.
  • @bvj Frågan handlar uttryckligen med + form av -exec till find. Detta svar korrigerar ett problem som användaren som ställer frågan inte har.

Svar

Jag hade min andel huvudvärk med exec-syntaxen tidigare. de flesta dagar nu föredrar jag den trevligare bash-syntaxen:

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

Det har vissa begränsningar när du vill behandla filerna som en grupp, eftersom var och en utvärderas seriellt, men du kan röra utdata någon annanstans helt fint

Kommentarer

  • Även om detta tenderar att fungera är det betydligt mindre användbart än den rena sökversionen eftersom den kan inte hantera filer med blanksteg i namnet korrekt.
  • Nej, gör det inte ’. Detta bryts så snart filerna innehåller mellanslag och andra ”konstiga” karaktärer. Detta är också mer komplext och långsammare än find … -exec … \;, så ’ är ingen anledning att använda detta även om du vet att dina filnamn är tämja.
  • det var till hjälp för min situation där jag behövde köra flera logikrader baserat på filnamnen (som att ta bort tecken, skapa kataloger och sedan flytta filerna). Att försöka hitta att göra flera saker i en exec var för mycket huvudvärk under de 5 minuter jag ville spendera på detta. Mina filnamn var tama och detta löste mitt problem 🙂

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *