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 '%smichell@server01:~$ printf '%s\0' * | xargs -0 rm' * | xargs -0 rm
– Nebo time echo a xargs:
michell@server01:~$ time echo -n * | tr ' ' 'michell@server01:~$ time echo -n * | tr ' ' '\0' | xargs -0 rm' | 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.
Michal Šika