IT Blok

kutilovo živobytí kromě www.msi-elektro.cz

Chyba „Argument is too long“ a její řešení

Na linuxu se nám při operacích s velkým počtem souborů může objevit chyba -bash: /bin/rm: Argument is too long. Jak ji vyřešit si ukážeme v tomto článku.

Chyba se objeví, když chceme smazat, přesunout nebo zkopírovat obsah adresáře, kde je velké množství souborů. Shell totiž může přijmout jen omezený počet argumentů příkazu, který v něm spustíme. Pokud tento počet přesáhneme objeví se chybová hláška: -bash: /bin/rm: Argument list too long
Například můžeme zjistit, maximální počet argumentů:

michell@server01:~$ getconf ARG_MAX
2621440
michell@server01:~$

Tady jasně vidíme, že počet maximální počet argumentů na mém serveru je 2621440, což je celkem dost, ale leckdy to nemusí stačit.
Takže když se objeví toto

michell@server01:~$ rm *
-bash: /bin/rm: Argument list too long
michell@server01:~$

znamená to, že v adresáři je více než 2621440 souborů, proto se příkaz neprovede. Níže uvedené příklady platí i pro další operace, jako je přesun (mv) a kopírování (cp) souborů!

Tady je několik způsobů, které můžeme použít.
– Jestli jsou v adresáři jen soubory, které můžeme všechny smazat, tak nejjednodušší a nejrychlejší je smazat celý adresář a následně vytvořit nový:

michell@server01:~$ cd ../
michell@server01:~$ ls -d muj-adresar
michell@server01:~$ rm -rf muj-adresar
michell@server01:~$ mkdir muj-adresar

Toto ale nemusí zafungovat v případě, že se adresář muj-adresar nachází v adresáři, na který nemáme oprávnění. Proto jsou zde ještě další možnosti.

– Dále můžeme použít cyklus for a soubory vložit do proměnné:

michell@server01:~$ for i in *; do rm "$i"; done

– O trochu rychlejší je použití příkazů printf a xargs:

michell@server01:~$ printf '%s\0' * | xargs -0 rm

– Nebo time echo a xargs:

michell@server01:~$ time echo -n * | tr ' ' '\0' | xargs -0 rm

Výše uvedené způsoby řešení mají ale jednu nevýhodu. Mohou odstranit i soubory, které bychom si rádi v adresáři ponechali. Proto je vhodné použití regulárních výrazů.
– Takto odstraníme pouze subory s koncovkou .txt:

michell@server01:~$ for i in *.txt; do rm "$i"; done

– Jako další rozdělení je možno použít podmínku, aby se smazaly soubory, které mají koncovku .txt a jejich název začíná na a nebo b:

michell@server01:~$ rm a*.txt
michell@server01:~$ rm b*.txt

– Předchozí příklad je možné ještě pomocí cyklu for upravit na všechna písmena:

michell@server01:~$ for i in $( echo {a..z} ); do rm $i*.txt; done

– Nebo za použití příkazu find a výběru souborů starší než x dnů:

michell@server01:~$ for i in $( find * -mtime +5 ); do rm $i; done

Možností je velké množství a lze je různě kombinovat a vylepšovat. Toto jsou pouze základní příklady, které můžeme dále rozvíjet a použít.