Ik “probeer het volgende commando uit te voeren:
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar "{}" +
Dit geeft een foutmelding:
find: missing argument to -exec
Ik kan “niet zien wat er mis is met dit commando, aangezien het lijkt overeen te komen met de man-pagina :
-exec commando {} +
Deze variant van de -exec optie voert het gespecificeerde commando uit op de geselecteerde bestanden, maar de opdrachtregel wordt opgebouwd door elke geselecteerde bestandsnaam aan het einde toe te voegen; het totale aantal aanroepen van de opdracht zal veel minder zijn dan het aantal overeenkomende bestanden. De opdrachtregel is op vrijwel dezelfde manier gebouwd als xargs zijn opdrachtregels. Slechts één exemplaar van “{}” is toegestaan binnen de opdracht. De opdracht wordt uitgevoerd in de startmap.
Ik heb ook geprobeerd:
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 "{}" \+
Reacties
Antwoord
Er was verschillende problemen met uw pogingen, inclusief backticks gebruikt in plaats van aanhalingstekens (verwijderd in latere bewerkingen van de vraag), ontbrekende aanhalingstekens waar ze nodig zijn, extra aanhalingstekens waar ze nutteloos zijn, ontbrekende haakjes om -o
clausules, en verschillende implementaties van find
gebruikt (zie de commentaren en chat voor details).
Hoe dan ook, het commando kan als volgt worden vereenvoudigd:
find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} +
of, als u een archaïsche GNU-zoekversie gebruikt, zou dit altijd moeten werken:
find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \;
Opmerkingen
- Oeps, ze waren bedoeld als aanhalingstekens en niet als backticks.
- Aanhalingstekens zouden nutteloos zijn als
{}
heeft geen specifieke betekenis voor de shell. - Van find man-paginas: ” De string ‘ { } ‘ is vervangen door de huidige bestandsnaam die overal wordt verwerkt waar het voorkomt in de argumenten van het commando, niet alleen in argumenten waar het alleen staat, zoals in sommige versies van find. Beide constructies moeten mogelijk worden geëscaped (met een ‘ \ ‘) of geciteerd om ze te beschermen tegen uitbreiding door de shell. ”
- Ik heb dat inderdaad gelezen in de handleiding, maar het feit is dat er geen shell is waarvan ik ‘ ben op de hoogte van dat vereist het citeren van de accolades. Welke shell gebruik je?
- bash. Met of zonder de aanhalingstekens krijg ik de fout sowieso.
Antwoord
“ontbrekend argument voor -exec
“betekent meestal dat het argument voor – exec
zijn terminator mist. De terminator moet ofwel een argument zijn dat alleen het teken ;
bevat (dat tussen aanhalingstekens moet worden geplaatst in een shell-opdracht, dus het wordt meestal geschreven als \;
of ";"
), of twee opeenvolgende argumenten die {}
en +
bevatten.
Stephane Chazelas heeft vastgesteld dat je “een oudere versie van GNU find gebruikt die geen -exec … {} +
, alleen -exec {} \;
.Hoewel GNU een late gebruiker was van -exec … {} +
, raad ik u aan om een minder antiek toolpakket aan te schaffen (zoals Cygwin , die git bevat en nog veel meer, of GNUwin32 , die git mist maar niet de slechte-werknemer-probeert-linux-te-gebruiken -but-we-impose-windows-vibe die Cygwin geeft). Deze functie is toegevoegd in versie 4.2.12, meer dan 9 jaar geleden (het was de laatst geïdentificeerde functie om GNU find
POSIX-compatibel).
Als je bij een oudere GNU-vondst wilt blijven, kun je -print0
gebruiken met xargs -0
om een vergelijkbare functionaliteit te krijgen: gegroepeerde opdrachtuitvoering, die willekeurige bestandsnamen ondersteunt.
find a/folder b/folder -name "*.c" -o -name "*.h" -print0 | xargs -0 grep -I foobar /dev/null
Citeer altijd de jokertekens op de find
opdrachtregel. Anders, als u deze opdracht uitvoert vanuit een map met .c
bestanden, zal de niet-geciteerde *.c
d worden uitgebreid naar de lijst met .c
bestanden in de huidige directory.
/dev/null
toevoegen aan de grep
opdrachtregel is een truc om ervoor te zorgen dat grep altijd de bestandsnaam afdrukt, zelfs als find
toevallig één overeenkomst vindt. Met GNU find is een andere methode om de optie -H
door te geven.
Reacties
- Wat doe je bedoelen met slechte-werknemer-die-linux-probeert-te-gebruiken maar-we-leggen-windows-vibe die cygwin geeft?
- GNUwin32 heeft ‘ niet verwacht 🙁
- Zie mijn opmerking (en) op de vraag.
- De aanhalingstekens rond de semi werkten vanuit een package.json-script.
Answer
Als een commando zoals
find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} +
fout retourneert
find: missing argument to -exec
de waarschijnlijke oorzaak is een te oude GNU find
die geen syntaxis ondersteunt -exec mycommand {} +
. In dat geval is vervanging met lage prestaties het uitvoeren van -exec mycommand {} \;
waarmee de mycommand
eenmaal wordt uitgevoerd voor elk gevonden doel in plaats van meerdere doelen te verzamelen en het mycommand
slechts één keer draaien.
Maar GNU find
doet s ondersteunen bijv.
find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts +
omdat GNU find
alleen letterlijke combinaties ondersteunt {} +
in plaats van meer algemeen {} additional parameters +
. Merk op dat er niets tussen de accolades en het +
-teken kan staan. Als u dit probeert, krijgt u dezelfde foutmelding:
find: missing argument to -exec
De oplossing is om de syntaxis {} additional parameters \;
te gebruiken die werkt wel, maar voert de opdracht eenmaal uit voor elk gevonden doel. Als je meer prestatie nodig hebt met GNU find
, moet je een wrapper-script schrijven dat extra parameters aan de opgegeven argumenten kan toevoegen. Iets als
#!/bin/bash exec mycommand "$@" additional parameters
zou goed genoeg moeten zijn. Of, als u geen tijdelijk bestand wilt maken, kunt u one-liner gebruiken om de volgorde van parameters als volgt te wijzigen:
find . -type f -and -name "*.ttf" -exec bash -c "mycommand "$@" extra arguments" {} +
die zal uitvoeren mycommand {list of ttf files} extra arguments
. Houd er rekening mee dat u mogelijk speciale escape-tekens moet verdubbelen voor de bash na de -c
vlag.
Reacties
- (1) Het deel van het bovenstaande dat de vraag daadwerkelijk beantwoordt, is al door andere mensen gegeven. (2) Wat u beschrijft is geen fout of tekortkoming in GNU
find
, maar het juiste gedrag gespecificeerd door POSIX . - +1 Eindelijk, iemand die antwoordt waarom aanvullende parameters niet ‘ werken! Het lijkt een tekortkoming in de POSIX-definitie.
- Als je ‘ ve GNU
find
je ‘ hebben waarschijnlijk GNUcp
. In dit geval zou jefind ... -exec cp --target-directory ~/.fonts {} +
kunnen gebruiken om de{}
aan het einde van de executiereeks te houden.
Answer
find . -type f -perm 0777 -exec chmod 644 {}\;
kreeg een foutmelding find: missing argument to ``-exec"
.
Door ruimte toe te voegen tussen {}
en \
is het opgelost:
find . -type f -perm 0777 -print -exec chmod 644 {} \;
Reacties
- Er is geen dergelijk probleem in de
find
commando in de betreffende vraag. - In vraag is het niet, prima, dat ik het begreep, maar het probleem is hetzelfde ” find: ontbrekend argument naar “ -exec ‘ “, kan het probleem optreden door een andere reden, antwoordde ik omdat ik dezelfde probleemstelling zag.
- @Kusalananda veel verdriet, de noob bood een oplossing voor de gerapporteerde fout die door het OP wordt vermeld in zowel de titel als de hoofdtekst van de vraag.
- @bvj De vraag behandelt expliciet met de
+
vorm van de-exec
optie naarfind
. Dit antwoord corrigeert een probleem dat de gebruiker die de vraag stelt niet heeft.
Antwoord
Ik had mijn deel van de hoofdpijn met de exec-syntaxis in het verleden. de meeste dagen geef ik de voorkeur aan de mooiere bash-syntaxis:
for f in `find a/folder b/folder -name "*.[ch]"`; do grep -I foobar $f; done
Het heeft enkele beperkingen als je de bestanden als een groep wilt behandelen, aangezien elk serieel wordt geëvalueerd, maar je kunt de uitvoer prima ergens anders heen sturen.
Opmerkingen
- Hoewel dit de neiging heeft te werken, is het aanzienlijk minder nuttig dan de pure-find-versie omdat het kan bestanden met spaties in de naam niet correct behandelen.
- Nee, ‘ doe dit niet. Dit wordt afgebroken zodra de bestanden spaties en andere “rare” tekens bevatten. Dit is ook ingewikkelder en langzamer dan
find … -exec … \;
, dus er is ‘ geen reden om dit te gebruiken, zelfs als u weet dat uw bestandsnamen zijn tam. - dit was handig voor mijn situatie waarin ik meerdere regels logica moest draaien op basis van de bestandsnamen (zoals het verwijderen van tekens, het maken van mappen en het verplaatsen van de bestanden). Proberen te vinden om meerdere dingen tegelijk te doen
exec
was te veel hoofdpijn voor de 5 minuten die ik hieraan wilde besteden. Mijn bestandsnamen waren tam en dit loste mijn probleem op 🙂
+
aan het einde?find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
find
. Hoewel de-exec cmd {} +
-variant POSIX is en beschikbaar is sinds de jaren 80, heeft GNU deze pas (relatief) recentelijk (2005) toegevoegd. Wat zegtfind --version
je?-exec {} +
is toegevoegd in 4.2.12 in 2005. In oudere GNU-vondsten kun je de (non-POSIX)-print0 | xargs -r0
gebruiken om iets op te halen vergelijkbaar.4.1
komt uit 1994.-name
patroon argumenten moeten tussen aanhalingstekens worden geplaatst:-name "*.c" -o -name "*.h"
. Dit is waar, hoewel het geen verband houdt met de fout-exec
. U zult zien dat alle andere antwoorden de jokertekens tussen aanhalingstekens zetten, hoewel alleen Gilles het vermeldt. … (Vervolg)-name "*.[ch]"
zonder uitleg. Dit heeft de voordelen van het vereenvoudigen van de opdrachtregel en, in het bijzonder, het elimineren van de-o
. Het is moeilijk om uitdrukkingen te vinden die betrekking hebben op-o
. De jouwe is verkeerd; als je commando is gerepareerd zodat het geen foutmelding geeft (zoals in het antwoord van Gilles), zal hetgrep
alleen uitvoeren op de.h
bestanden. U moet'(' -name '*.c' -o -name '*.h' ')'
doen.