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