it-swarm-eu.dev

Seznam argumentů je příliš dlouhý na ls

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.

51
user19016

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"
53
Coren

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

11
Mikel

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

9
Keith Thompson

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

1
Bram

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.

1