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
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 GNUcp
. I det här fallet kan dufind ... -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
tillfind
. 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 🙂
+
i slutet?find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
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ägerfind --version
?-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.-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.)-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 detgrep
endast på.h
filer. Du måste göra'(' -name '*.c' -o -name '*.h' ')'
.