Chápu, že -exec
může mít možnost +
napodobit chování xargs
. Existuje nějaká situace, kdy byste upřednostňovali jeden formulář před druhým?
Osobně mám tendenci upřednostňovat první formulář, i když jen proto, abych nepoužíval rouru. Určitě si myslím, že vývojáři find
musí provést příslušnou optimalizaci. Mám pravdu?
Odpovědět
Možná budete chtít zřetězit hovory, abyste našli (jednou, když jste se dozvěděli, že je možné , což může být dnes). To je samozřejmě možné, pouze pokud zůstanete v nálezu. Jakmile se připojíte k xargs, je to mimo rozsah.
Malý příklad, dva soubory a.lst a b.lst:
cat a.lst fuddel.sh fiddel.sh cat b.lst fuddel.sh
Tady žádný trik – jednoduše skutečnost, že oba obsahují „fuddel“, ale pouze jeden obsahuje „fiddel“.
Předpokládejme, že jsme to nevěděli. Hledáme soubor, který odpovídá 2 podmínkám:
find -exec grep -q fuddel {} ";" -exec grep -q fiddel {} ";" -ls 192097 4 -rw-r--r-- 1 stefan stefan 20 Jun 27 17:05 ./a.lst
Možná znáte syntaxi grepu nebo jiného programu, který předá oba řetězce jako podmínku, ale to “ nejde o smysl. Zde lze použít každý program, který může vracet true nebo false, a daný soubor jako argument – grep byl jen populární příklad.
A všimněte si, že můžete sledovat find -exec s dalšími vyhledávacími příkazy, například -ls nebo -delete nebo něco podobného. Pamatujte, že smazání nejenže odstraní rm (odstraní soubory), ale i rmdir (odebere adresáře).
Takový řetězec se čte jako kombinace příkazů AND, pokud není uvedeno jinak (konkrétně s přepínačem -or
(a parens (které vyžadují maskování))).
Takže neopustíte řetězec hledání, což je užitečná věc. Nevidím žádnou výhodu v používání -xargs, protože při předávání souborů musíte být opatrní, což je něco, co najít nemusí – automaticky předává každý soubor jako jediný argument.
Pokud se domníváte, že potřebujete nějaké maskování pro nálezy {} závorky , neváhejte navštívit mou otázku, která žádá o důkazy. Moje tvrzení zní: „Don. T.
Komentáře
- Tento příspěvek mi otevřel oči pro nový způsob používání
find
. Mnohokrát děkuji! - “ Nevidím ‚ při používání žádnou výhodu -xargs „. Jak ‚ je
-exec
způsob, jakxargs -P4
takže tři ze čtyř jader nezůstanou nečinná? - @DamianYerrick: Ukončit příkaz -exec není v „; “ ale se znaménkem + (/ plus).
Odpověď
Bezpečné pipování názvů souborů do xargs
vyžaduje, aby váš find
podporoval -print0
a vaše xargs
má odpovídající možnost si ji přečíst (--null
nebo -0
). Jinak názvy souborů s unprintab Znaky nebo zpětná lomítka nebo uvozovky nebo mezery v názvu mohou způsobit neočekávané chování. Na druhou stranu find -exec {} +
je ve POSIX find
spec , takže je přenosný a je přibližně stejně bezpečný jako find -print0 | xargs -0
a rozhodně bezpečnější než find | xargs
. Doporučuji nikdy nedělat find | xargs
bez -print0
.
Komentáře
Odpověď
Pokud použijete formulář -exec ... ;
(pamatuji si uniknout středníkem), spustíte příkaz jednou pro každý název souboru. Pokud použijete -print0 | xargs -0
, spustíte více příkazů na jeden název souboru. Měli byste určitě použít -exec +
formulář, který umisťuje více souborů do jednoho příkazového řádku a je mnohem rychlejší, když se jedná o velký počet souborů.
Velkou výhodou použití xargs
je schopnost paralelně spouštět více příkazů pomocí xargs -P
. U vícejádrových systémů to může přinést obrovské časové úspory.
Komentáře
- Měli jste na mysli
-P
místo-p
. Pamatujte, žexargs -P
není ve standardu POSIX, zatímcofind -exec {} +
ano, což je důležité, pokud se chystáte na přenositelnost. - @Alexios ‚ nemusíte uniknout znaménku plus, protože nemá pro shell zvláštní význam:
find /tmp/ -exec ls "{}" +
funguje dobře. - Samozřejmě, samozřejmě. ‚ Utekl jsem po
-exec
tak dlouho (jsem ‚ ma masochist , Ani ‚ nepoužívám uvozovky k úniku{}
, vždy zadám\{\}
; don ‚ t ask), vše vypadá, že teď musí uniknout. - @Alexios: Pokud najdete příklad (kromě toho, že jste masochista), kde maskování složených závorek je užitečné, uveďte jej prosím jako odpověď na moji otázku zde – afaik tato nápověda je zastaralá a pouze relikt na stránce. Nikdy jsem neviděl příklad, kde by
find /tmp/ -exec ls {} +
nefungoval ‚. - Pro mě je to svalová paměť utvářená ve dnech SunOS 4. Jelikož to dělám už roky, úplně jsem si nevšiml, když
bash
začal závorky přijímat doslovně. Jsem si ‚ docela jistý, že alespoň jeden ze starých granátů, které jsem použil ‚, použil hissy fit, pokud šle nebyly ‚ T uniklo.
Odpověď
Pokud jde o výkon, myslel jsem si, že -exec … +
by prostě bylo lepší, protože je to jediný nástroj, který dělá veškerou práci, ale součást dokumentace GNU findutil říká, že -exec … +
může být v některých případech méně efektivní:
[najít pomocí
-exec … +
] může být méně efektivní než některá použitíxargs
; napříkladxargs
umožňuje vytváření nových příkazových řádků, zatímco předchozí příkaz se stále spouští, a umožňuje zadat několik příkazů, které se mají spouštět paralelně. Konstrukcefind ... -exec ... +
má však výhodu široké přenositelnosti. GNU findutils nepodporovalo „-exec ... +
do verze 4.2.12 [leden 2005] ; jedním z důvodů je, že v každém případě již akci „-print0
provedla.
Nebyl jsem si úplně jistý, co to znamená, tak jsem se zeptal v chatu, kde derobert vysvětlil to takto:
find
pravděpodobně mohl pokračovat v hledání další dávky souborů, zatímco-exec … +
běží, ale nedělá to.
find … | xargs …
ano, protože pak je hledání jiný proces a udržuje běží, dokud se vyrovnávací paměť potrubí nezaplní
(Formátování mnou.)
Takže je to. Pokud ale na výkonu opravdu záleží, budete muset provést realistické srovnávací testy, nebo se dokonce sami sebe zeptat, zda byste vůbec chtěli použít shell pro takové případy.
Tady na tomto webu si myslím, že je lepší radit lidem, aby použijte -exec … +
formulář, kdykoli je to možné, protože je to jednodušší a z důvodů zmíněných v dalších odpovědích zde (např. manipulace se zvláštními názvy souborů, aniž byste museli hodně přemýšlet).
find … -exec … {} +
je OpenBSD, které tuto funkci získalo až ve verzi 5.1 vydané v roce 2012. Všechny BSD měly-print0
několik let, dokonce i OpenBSD (i když se této funkci na chvíli také bránilo). Solaris se naopak drží funkcí POSIX, takže získáte-exec +
a ne-print0
.-print0
je bolest, i když můžete argumentovatxargs --delimiter "\n"
není ‚ t ekvivalent, ‚ jsem první nikdy nepoužil po objevení druhé .-0
větší bolest než--delimiter "\n"
.-0
GNUxargs
potřebuje-r
vyhnout se spuštění příkazu, pokud ‚ nemá žádný vstup.| xargs -r0 cmd
je to, žecmd
‚ s stdin je ovlivněn (v závislosti naxargs
implementaci, ‚ s/dev/null
nebo kanálu.