Další odpovědí je vynutit xargs
zpracovávat příkazy v dávkách. Například do delete
soubory 128 kB
najednou, cd
do adresáře a spusťte toto:
echo *.pdf | xargs -n 100 rm
tl;dr
Je to omezení jádra na velikost argumentu příkazového řádku. Použijte for
místo toho smyčka.
Původ problému
Toto je systémový problém související s execve
a ARG_MAX
konstantní. O tom je spousta dokumentace (viz man execve, wiki debianu, podrobnosti ARG_MAX).
V podstatě expanze vytváří příkaz (se svými parametry), která překračuje ARG_MAX
limit.Na jádře 2.6.23
, limit byl nastaven na 128 kB
. Tato konstanta byla zvýšena a její hodnotu můžete získat provedením:
getconf ARG_MAX
# 2097152 # on 3.5.0-40-generic
Řešení:Pomocí for
Smyčka
Použijte for
smyčka, jak je doporučeno na BashFAQ/095 a není zde žádný limit kromě RAM/paměti:
Spusťte nasucho, abyste se ujistili, že smaže to, co očekáváte:
for f in *.pdf; do echo rm "$f"; done
A spusťte jej:
for f in *.pdf; do rm "$f"; done
Toto je také přenosný přístup, protože glob mají silné a konzistentní chování mezi shelly (součást specifikace POSIX).
Poznámka: Jak bylo uvedeno v několika komentářích, je to skutečně pomalejší, ale lépe udržovatelné, protože dokáže přizpůsobit složitější scénáře, např. kde člověk chce udělat více než jen jednu akci.
Řešení:Pomocí find
Pokud na tom trváte, můžete použít find
ale opravdu nepoužívejte xargs protože "je nebezpečné (rozbité, zneužitelné atd.) při čtení vstupu bez hodnoty NUL" :
find . -maxdepth 1 -name '*.pdf' -delete
Pomocí -maxdepth 1 ... -delete
místo -exec rm {} +
umožňuje find
jednoduše spustit požadovaná systémová volání sama bez použití externího procesu, tedy rychlejší (díky komentáři @chepner).
Odkazy
- Zobrazuje se mi „Seznam argumentů je příliš dlouhý“. Jak mohu zpracovat velký seznam po částech? @ wooledge
- execve(2) – manuálová stránka Linuxu (hledejte ARG_MAX);
- Chyba:Příliš dlouhý seznam argumentů @ wiki Debianu;
- Proč se mi při předávání argumentů v uvozovkách zobrazuje „/bin/sh:Seznam argumentů je příliš dlouhý“? @ SuperUser
find
má -delete
akce:
find . -maxdepth 1 -name '*.pdf' -delete
Důvodem je to, že bash ve skutečnosti rozšiřuje hvězdičku na každý odpovídající soubor a vytváří velmi dlouhý příkazový řádek.
Zkuste toto:
find . -name "*.pdf" -print0 | xargs -0 rm
Upozornění: toto je rekurzivní vyhledávání a najde (a odstraní) soubory také v podadresářích. Zaměřte se na -f
na příkaz rm, pouze pokud jste si jisti, že nechcete potvrzení.
Chcete-li, aby příkaz nebyl rekurzivní, můžete provést následující:
find . -maxdepth 1 -name "*.pdf" -print0 | xargs -0 rm
Další možností je použít find -delete
příznak:
find . -name "*.pdf" -delete