GNU/Linux >> Znalost Linux >  >> Linux

Chyba příliš dlouhého seznamu argumentů pro příkazy rm, cp, mv

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-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

Linux
  1. Grep pro více řetězců v souborech a pak seznam souborů v pořadí velikosti?

  2. Bash for smyčky Příklady

  3. Nelze odebrat soubory z adresáře s chybou „Seznam argumentů je příliš dlouhý“

  1. Jak omezit hloubku pro rekurzivní seznam souborů?

  2. Chyba SFTP Přijatá zpráva je příliš dlouhá

  3. Nelze najít chybu pkg-config

  1. Cheat sheet pro běžné linuxové příkazy

  2. Intermittent OSError:[Errno 7] Příliš dlouhý seznam argumentů s krátkým příkazem (~125 znaků)

  3. Jak vypsat seznam složek pomocí příkazů bash?