Pokouším se spustit následující příkaz:
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar "{}" +
Toto vrací chybu:
find: missing argument to -exec
Nevidím, co je s tímto příkazem špatně, protože se zdá, že odpovídá manuálové stránce :
-exec příkaz {} +
Tato varianta volby -exec spustí zadaný příkaz na vybraných souborech, ale příkazový řádek je vytvořen připojením každého vybraného názvu souboru na konci; celkový počet faktur za příkaz bude mnohem menší než počet spárovaných souborů. Příkazový řádek je vytvořen podobně, jako xargs vytváří své příkazové řádky. V příkazu je povolena pouze jedna instance znaku „{}“. Příkaz je spuštěn ve výchozím adresáři.
Zkoušel jsem také:
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 "{}" \+
Komentáře
Odpovědět
Bylo několik problémů s vašimi pokusy, včetně zpětných lístků použitých místo uvozovek (odstraněno v pozdějších úpravách otázky), chybějící uvozovky, pokud jsou požadovány, zvláštní uvozovky, pokud jsou k ničemu, chybějící závorky do skupiny -o
a různé implementace použitých find
(podrobnosti viz komentáře a chat).
Každopádně lze příkaz zjednodušit takto:
find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} +
nebo, pokud používáte archaickou verzi GNU find, mělo by to vždy fungovat:
find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \;
Komentáře
- Jejda, měly to být uvozovky, nikoli backticks.
- Citáty by byly k ničemu, protože
{}
nemá pro shell žádný konkrétní význam. - Na stránkách find man: “ Řetězec ‚ { } ‚ je nahrazen aktuálním názvem souboru, který se zpracovává všude, kde se vyskytuje v argumentech příkazu, nejen v argumentech, kde je sám, jako v některých verzích find. Obě tyto konstrukce bude pravděpodobně nutné uniknout (pomocí ‚ \ ‚), aby byly chráněny před rozšířením o prostředí. “
- Skutečně jsem to četl na manuálové stránce, ale faktem je, že neexistuje žádný shell, o kterém bych ‚ věděl to vyžaduje citaci složených závorek. Jaký shell používáte?
- bash. S uvozovkami nebo bez nich i tak dostávám chybu.
Odpovědět
„chybějící argument -exec
”obvykle znamená, že argumentu – exec
chybí jeho zakončení. Terminátor musí být buď argument obsahující pouze znak ;
(který je třeba uvést v příkazu prostředí, takže se obvykle píše \;
nebo ";"
) nebo dva po sobě jdoucí argumenty obsahující {}
a +
.
Stephane Chazelas zjistil , že používáte starší verzi GNU find, která nepodporuje -exec … {} +
, pouze -exec {} \;
.Přestože GNU byl pozdním osvojitelem -exec … {} +
, doporučuji vám zakoupit si méně starožitnou sadu nástrojů (například Cygwin , který obsahuje git a mnohem více, nebo GNUwin32 , kterému chybí git, ale nemá špatného zaměstnance, který se snaží použít linux -but-we-impose-windows vibe that Cygwin gives). Tato funkce byla přidána ve verzi 4.2.12, před více než 9 lety (byla to poslední identifikovaná funkce, která vytvořila GNU find
Kompatibilní s POSIX).
Pokud se chcete držet staršího GNU nálezu, můžete použít -print0
s xargs -0
pro získání podobné funkce: seskupené provádění příkazů, podpora libovolných názvů souborů.
find a/folder b/folder -name "*.c" -o -name "*.h" -print0 | xargs -0 grep -I foobar /dev/null
Vždy uvádějte zástupné znaky na find
příkazový řádek. V opačném případě, pokud spustíte tento příkaz z adresáře obsahujícího soubory .c
, neoznačený *.c
woul d být rozšířen na seznam .c
souborů v aktuálním adresáři.
Přidání /dev/null
do grep
příkazový řádek je trik, který zajistí, že grep vždy vytiskne název souboru, i když find
najde jednu shodu. Při hledání GNU je další metodou předat volbu -H
.
Komentáře
- Co děláte míněno špatným zaměstnancem, který se snaží použít linux-ale-my-vnucujeme-Windows atmosféru, kterou dává Cygwin?
- GNUwin32 neočekává ‚ 🙁
- Podívejte se na moje komentáře k otázce.
- Citace kolem semifinále fungovaly ze skriptu package.json.
Odpověď
Pokud příkaz jako
find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} +
vrátí chybu
find: missing argument to -exec
pravděpodobnou příčinou je příliš starý GNU find
, který nepodporuje syntaxi -exec mycommand {} +
. V takovém případě má být nahrazením s nízkým výkonem spuštěno -exec mycommand {} \;
, které spustí mycommand
jednou pro každý nalezený cíl namísto shromažďování více cílů a spuštění mycommand
pouze jednou.
GNU find
doe však nepodporuje např.
find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts +
protože GNU find
podporuje pouze doslovnou kombinaci {} +
místo obecnějších {} additional parameters +
. Všimněte si, že mezi složenými závorkami a znakem +
nemůže být nic. Pokud to zkusíte, zobrazí se stejná chyba:
find: missing argument to -exec
Řešením je použít syntaxi {} additional parameters \;
která funguje, ale provede příkaz jednou pro každý nalezený cíl. Pokud potřebujete větší výkon s GNU find
, musíte napsat obalový skript, který může k zadaným argumentům připojit další parametry. Něco jako
#!/bin/bash exec mycommand "$@" additional parameters
by mělo být dost dobré. Nebo pokud nechcete vytvořit dočasný soubor, můžete použít jednořádkovou linku ke změně pořadí parametrů takto:
find . -type f -and -name "*.ttf" -exec bash -c "mycommand "$@" extra arguments" {} +
, který provede mycommand {list of ttf files} extra arguments
. Nezapomeňte, že po příznaku -c
možná budete muset zdvojnásobit speciální znaky pro bash.
Komentáře
- (1) Část výše uvedeného, která ve skutečnosti odpovídá na otázku, již byla dána jinými lidmi. (2) To, co popisujete, není chyba nebo nedostatek GNU
find
, ale správné chování určené POSIX . - +1 Konečně někdo, kdo odpovídá, proč další parametry nefungují ‚! Vypadá to jako nedostatek v definici POSIX.
- Pokud ‚ ve GNU
find
vy ‚ pravděpodobně dostal GNUcp
. V tomto případě byste mohlifind ... -exec cp --target-directory ~/.fonts {} +
ponechat{}
na konci řetězce provádění.
odpověď
find . -type f -perm 0777 -exec chmod 644 {}\;
došlo k chybě find: missing argument to ``-exec"
.
Přidání mezery mezi {}
a \
opraveno:
find . -type f -perm 0777 -print -exec chmod 644 {} \;
Komentáře
- V
find
příkaz v dané otázce. - V otázce to není v pořádku, rozuměl jsem, ale problém je stejný “ find: missing argument na „ -exec ‚ „, k problému může dojít z různých důvodů, odpověděl jsem, protože jsem viděl stejný problém.
- @Kusalananda dobrý zármutek, noob poskytl řešení pro nahlášenou chybu, která je uvedena v OP v názvu i textu otázky.
- @bvj Otázka se výslovně zabývá s
+
formou-exec
možnostifind
. Tato odpověď opravuje problém, který uživatel, který otázku položí, nemá.
Odpověď
Měl jsem svůj podíl bolesti hlavy se syntaxí exec v minulosti. po většinu dní dávám přednost hezčí bash syntaxi:
for f in `find a/folder b/folder -name "*.[ch]"`; do grep -I foobar $f; done
Má určitá omezení, pokud chcete se soubory zacházet jako se skupinou, protože každá je hodnocena sériově, ale výstup můžete poslat jinde v pohodě
Komentáře
- I když to má tendenci fungovat, je to podstatně méně užitečné než verze s čistým nálezem, protože nemůže správně zpracovat soubory s mezerami v názvu.
- Ne, nedělejte to ‚. Toto se přeruší, jakmile soubory obsahují mezery a další „divné“ znaky. To je také složitější a pomalejší než
find … -exec … \;
, takže ‚ není důvod toto používat, i když víte, že názvy vašich souborů jsou zkrotit. - to bylo užitečné pro mou situaci, kdy jsem potřeboval spustit více řádků logiky na základě názvů souborů (například odstranění znaků, vytváření adresářů a následné přesunutí souborů). Pokoušet se najít více věcí v jednom
exec
bylo příliš mnoho bolesti hlavy na těch 5 minut, které jsem tomu chtěl věnovat. Jména mých souborů byla krotká a to můj problém vyřešilo 🙂
+
na konci?find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
find
. Ačkoli-exec cmd {} +
varianta je POSIX a je k dispozici od 80. let, GNU find ji přidal (relativně) nedávno (2005). Co vámfind --version
říká?-exec {} +
byl přidán ve 4.2.12 v roce 2005. Ve starších nálezech GNU můžete k získání něčeho použít (non-POSIX)-print0 | xargs -r0
podobný.4.1
je z roku 1994.-name
vzor argumenty by měly být citovány:-name "*.c" -o -name "*.h"
. To je pravda, i když to nesouvisí s chybou-exec
. Všimnete si, že všechny ostatní odpovědi dávají zástupné znaky do uvozovek, ačkoli to zmiňuje pouze Gilles. … (Cont’d)-name "*.[ch]"
. To má výhody ve zjednodušení příkazového řádku a konkrétně v eliminaci-o
. Najít výrazy zahrnující-o
je těžké napravit. Vaše se mýlí; pokud je váš příkaz opraven tak, aby nedocházelo k chybám (jako v Gillesově odpovědi), bude spuštěngrep
pouze na.h
soubory. Musíte udělat'(' -name '*.c' -o -name '*.h' ')'
.