Při pokusu o ls *.txt | wc -l
adresář, který obsahuje mnoho souborů:
-bash: /bin/ls: Argument list too long
Závisí práh tohoto „Seznamu argumentů“ na distro nebo na specifikaci počítače? Obvykle bych výsledek tak velkého výsledku poslal na některé další příkazy (wc -l
například), takže se nestarám o limity terminálu.
Vaše chybová zpráva seznam argumentů je příliš dlouhý pochází z ***** of ls *.txt
.
Tento limit představuje bezpečnost pro binární programy i pro vaše jádro. Viz ARG_MAX, maximální délka argumentů pro nový proces , kde jsou další informace o tom, jak se používá a vypočítává.
Na velikost potrubí není takové omezení. Můžete tedy jednoduše zadat tento příkaz:
find -type f -name '*.txt' | wc -l
Pozn .: Na moderním Linuxu budou podivné znaky v názvech souborů (jako jsou nové řádky) unikány pomocí nástrojů jako ls
nebo find
, ale budou zobrazeny od *****. Pokud jste na starém Unixu, budete potřebovat tento příkaz
find -type f -name '*.txt' -exec echo \; | wc -l
NB2: Zajímalo by mě, jak lze vytvořit soubor s novým řádkem v názvu. Není to tak těžké, jakmile znáte ten trik:
touch "hello
world"
Závisí to hlavně na vaší verzi linuxového jádra.
Měli byste mít možnost vidět limit vašeho systému spuštěním
getconf ARG_MAX
který vám řekne maximální počet bajtů, které může mít příkazový řádek poté, co byl rozšířen Shell.
V systému Linux <2.6.23 je limit obvykle 128 KB.
V systému Linux> = 2.6.25 je limit buď 128 KB, nebo 1/4 velikosti zásobníku (viz ulimit -s
), podle toho, co je větší.
Všechny podrobnosti najdete na manuálové stránce execve (2) .
Bohužel potrubí ls *.txt
problém neopraví, protože limit je v operačním systému, nikoli v prostředí Shell.
Shell rozšiřuje *.txt
, poté se pokusí zavolat
exec("ls", "a.txt", "b.txt", ...)
a máte tolik souborů, které odpovídají *.txt
že překračujete limit 128 KB.
Budete muset udělat něco jako
find . -maxdepth 1 -name "*.txt" | wc -l
namísto.
(A viz komentáře Shawn J. Goffa níže o názvech souborů, které obsahují nové řádky.)
Další řešení:
ls | grep -c '\.txt$'
Přestože ls
produkuje více výstupu než ls *.txt
produkuje (nebo se pokouší produkovat), nespustí se do problému „argument příliš dlouhý“, protože nepředáváte žádné argumenty ls
. Všimněte si, že grep
má spíše regulární výraz než vzor odpovídající souboru.
Možná budete chtít použít:
ls -U | grep -c '\.txt$'
(za předpokladu, že vaše volba ls
tuto možnost podporuje). To říká, že ls
nebude třídit jeho výstup, což může ušetřit čas i paměť - av tomto případě na tom nezáleží, protože právě počítáte soubory. Prostředky vynaložené na třídění výstupu obvykle nejsou významné, ale v tomto případě již víme, že máte velmi velké množství *.txt
soubory.
A měli byste zvážit reorganizaci souborů, takže v jediném adresáři nemáte tolik. To může nebo nemusí být proveditelné.
MAX_ARG_PAGES se zdá být parametrem jádra. Použití find
a xargs
je typická kombinace pro řešení tohoto limitu, ale nejsem si jistý, že to bude fungovat pro wc
.
Potrubí výstupu find . -name \*\.txt
do souboru a počítání řádků v tomto souboru by mělo sloužit jako řešení.
Může to být špinavé, ale funguje to pro mé potřeby a v rámci mé kompetence. Nemyslím si, že to funguje velmi rychle, ale umožnilo mi to pokračovat ve svém dni.
ls | grep jpg | <something>
Dostal jsem 90 000 dlouhý seznam jpgs a dal jsem je do avconv, aby vygeneroval timelapse.
Dříve jsem používal ls * .jpg | avconv předtím, než jsem narazil na tento problém.