Når jeg kjører en kommando som ls */*/*/*/*.jpg
, får jeg feilen
-bash: /bin/ls: Argument list too long
Jeg vet hvorfor dette skjer: det er fordi det er en kjernegrense på mengden plass for argumenter til en kommando. Standardrådet er å endre kommandoen jeg bruker, for å unngå å kreve så mye plass for argumenter (f.eks. Bruk find
og xargs
).
Hva om jeg ikke vil endre kommandoen? Hva om jeg vil fortsette å bruke den samme kommandoen? Hvordan kan jeg få ting til å «bare fungere» uten å få denne feilen? Hvilke løsninger er tilgjengelige?
Kommentarer
- Nyttig lesing: Vanlige spørsmål om Bash 95 . Uten å endre kommandoen det er ' ikke mye du kan gjøre foruten å kompilere for å øke argumentlistens maksimale størrelse, eller endre katalogstrukturen slik at det blir færre filer.
- @ jw013 basert på Linux-kjerneversjonen kan det være mulig å øke argumentlisten – se unix.stackexchange.com/a/45161/8979 for detaljer om endringen i nylige systemer.
- @UlrichDangel, Yup, det er mulig! Se svaret mitt; svaret mitt viser hvordan du gjør det (på L inux, med en nylig nok kjerne).
Svar
På Linux er maksimum plass for kommando argumenter er 1/4 av mengden tilgjengelig stabelplass. Så, en løsning er å øke mengden tilgjengelig plass for stakken.
Kortversjon: kjør noe sånt som
ulimit -s 65536
Lengre versjon : Standard plass tilgjengelig for stakken er omtrent 8192 KB. Du kan se hvor mye plass som er tilgjengelig, som følger:
$ ulimit -s 8192
Velg et større tall, og angi hvor mye plass som er tilgjengelig for stakken. Hvis du for eksempel vil prøve å tillate opptil 65536 kB for stakken, kan du kjøre denne:
$ ulimit -s 65536
Du må kanskje leke med hvor stort dette trenger å være, ved hjelp av prøving og feiling. I mange tilfeller er dette en rask og skitten løsning som vil eliminere behovet for å endre kommandoen og utarbeide syntaksen til find
, xargs
osv. (selv om jeg er klar over at det er andre fordeler ved å gjøre det).
Jeg tror at dette er Linux-spesifikt. Jeg mistenker at det sannsynligvis ikke vil hjelpe på noe annet Unix-operativsystem (ikke testet).
Kommentarer
- Du kan bekrefte at dette fungerte : $ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
- Betyr dette at hvis jeg gjør stakkstørrelsen ubegrenset med
ulimit -s unlimited
vil kommandolinjestørrelsen være ubegrenset også?
Svar
I stedet for ls */*/*/*/*.jpg
, prøv:
echo */*/*/*/*.jpg | xargs ls
xargs
(1) vet, hva det maksimale antallet argumenter er på systemet, og vil bryte opp standardinngangen for å ringe den angitte kommandolinjen flere ganger uten flere argumenter enn den grensen, uansett hva den er (du kan også sette den lavere enn OS «maksimum ved hjelp av -n
alternativ).
Anta for eksempel at grensen er 3 argumenter og at du har fem filer. I så fall vil xargs
utføre ls
to ganger:
-
ls 1.jpg 2.jpg 3.jpg
-
ls 4.jpg 5.jpg
Dette er ofte perfekt, men ikke alltid – for eksempel kan du ikke stole på ls
(1) sortering alle oppføringene for deg riktig, fordi hver separate ls
-innkalling vil bare sortere delsettet av oppføringene gitt av xargs
.
Selv om du kan støte på grensen som foreslått av andre, vil det fortsatt være en grense – og en dag vil JPG-samlingen din vokse ut igjen. Du bør forberede skriptet ditt for å takle et uendelig antall …
Kommentarer
- Takk for ideen! Dette er ikke en dårlig løsning. To forbehold: 1. Dette bryter på kataloger og filnavn som har mellomrom i navnet sitt, så det ' er ikke en perfekt erstatning. 2. Skal det løpe inn i det samme problemet med
Argument list too long
, men forecho
i stedet forls
, på skjell derecho
ikke er en innebygd shell-kommando? (Kanskje det ikke er ' i de fleste skjell, så kanskje det er ' som ikke er relevant.) - Ja , spesialtegn i filnavn er et problem. Det beste alternativet er å bruke
find
med-print0
predikatet – og rør utgangen tilxargs
med-0
alternativ.echo
er et innebygd skall og lider ikke av kommandolinjebegrensningen tilexec
(3). - Dette fungerer med kommandoer som forventer variabelargumentet som siste parameter, for eksempel for
ls
, men hva gjør jeg når jeg vilmv
mange filer til en enkelt dir, f.eksmv * destdir
? Hvis*
gir " for mange args " feil, kan jeg ' t fårxargs
til å passere stiene som første tilmv
på en eller annen måte, eller kan jeg? - Sjekk man-siden for
xargs
på systemet ditt – på FreeBSD, for eksempel, vil-J
hjelpe deg med denne oppgaven. Hvis det ikke er noen måte å gjøre dette på operativsystemet ditt, må du ' skrive et tilpasset skript for å omorganisere argumentene. Noe som:destdir=$1; shift; mv "$@" "$destdir"
. Gi deretter dette nye skriptet tilxargs
:.... | xargs newscript $destdir
Svar
Denne Linux Journal-artikkelen gir 4 løsninger. Bare den fjerde løsningen innebærer ikke å endre kommandoen:
Metode # 4 innebærer manuelt å øke antall sider som er tildelt i kjernen for kommandolinje argumenter. Hvis du ser på include / linux / binfmts.h-filen, finner du følgende nær toppen:
/* * MAX_ARG_PAGES defines the number of pages allocated for arguments * and envelope for the new program. 32 should suffice, this gives * a maximum env+arg of 128kB w/4KB pages! */ #define MAX_ARG_PAGES 32
For å øke mengden minne dedikert til kommandolinjeargumentene, trenger du bare å oppgi MAX_ARG_PAGES-verdien med et høyere tall. Når denne redigeringen er lagret, er det bare å kompilere på nytt, installere og starte på nytt i den nye kjernen som du ville gjort normalt.
På mitt eget testsystem klarte jeg å løse alle problemene mine ved å heve denne verdien til 64. Etter omfattende testing har jeg ikke opplevd et eneste problem siden byttet. Dette er helt forventet siden selv med
MAX_ARG_PAGES
satt til 64, ville den lengst mulige kommandolinjen jeg kunne produsere bare oppta 256 kB systemminne – ikke veldig mye av dagens systemhardwarestandarder .Fordelene med metode nr. 4 er tydelige. Du kan nå bare kjøre kommandoen som normalt, og den fullføres vellykket. Ulempene er like klare. Hvis du øker mengden tilgjengelig minne til kommandolinjen utover mengden tilgjengelig systemminne, kan du opprette et DOS-angrep på ditt eget system og få det til å krasje. På spesielt flerbrukssystemer kan til og med en liten økning ha en betydelig innvirkning fordi hver bruker deretter tildeles ekstra minne. Test derfor alltid omfattende i ditt eget miljø, da dette er den tryggeste måten å avgjøre om Metode # 4 er et levedyktig alternativ for deg.
Jeg er enig i at begrensningen er alvorlig irriterende.