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

  • Zkusili jste uniknout + na konci? find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
  • Možná používáte starou verzi GNU 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ám find --version říká?
  • @Koveras, to by tedy bylo ono. -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.
  • JRFerguson poukázal (v odpovědi, která byla smazána), že -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)
  • (Cont’d) … odpověď jlliagre sbalí bez vysvětlení výraz názvu na -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ěn grep pouze na .h soubory. Musíte udělat '(' -name '*.c' -o -name '*.h' ')'.

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 GNU cp. V tomto případě byste mohli find ... -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žnosti find. 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 🙂

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *