Quando eseguo un comando come ls */*/*/*/*.jpg
, ottengo lerrore
-bash: /bin/ls: Argument list too long
So perché questo accade: è perché cè un limite del kernel sulla quantità di spazio per gli argomenti di un comando. Il consiglio standard è di cambiare il comando che utilizzo, per evitare di richiedere così tanto spazio per gli argomenti (ad esempio, usa find
e xargs
).
E se non volessi cambiare il comando? E se volessi continuare a usare lo stesso comando? Come posso fare in modo che le cose “funzionino” senza ricevere questo errore? Quali soluzioni sono disponibili?
Commenti
- Letture utili: Bash FAQ 95 . Senza modificare il comando ‘ non puoi fare molto oltre a ricompilare per aumentare la dimensione massima dellelenco di argomenti o modificare la struttura della directory in modo che ci siano meno file.
- @ jw013 in base alla versione del kernel Linux, potrebbe essere possibile aumentare lelenco degli argomenti – vedere unix.stackexchange.com/a/45161/8979 per i dettagli sulla modifica sistemi recenti.
- @UlrichDangel, Sì, è possibile! Guarda la mia risposta; la mia risposta mostra come farlo (su L inux, con un kernel abbastanza recente).
Answer
Su Linux, la quantità massima di spazio per il comando argomenti è 1/4 della quantità di spazio disponibile nello stack. Quindi, una soluzione è aumentare la quantità di spazio disponibile per lo stack.
Versione breve: eseguire qualcosa di simile
ulimit -s 65536
Versione più lunga : La quantità predefinita di spazio disponibile per lo stack è qualcosa come 8192 KB. Puoi vedere la quantità di spazio disponibile, come segue:
$ ulimit -s 8192
Scegli un numero maggiore e imposta la quantità di spazio disponibile per lo stack. Ad esempio, se vuoi provare a consentire fino a 65536 KB per lo stack, esegui questo:
$ ulimit -s 65536
Potrebbe essere necessario giocare con quanto grande è necessario essere, usando tentativi ed errori. In molti casi, questa è una soluzione rapida e sporca che eliminerà la necessità di modificare il comando e di elaborare la sintassi di find
, xargs
, ecc. (anche se mi rendo conto che ci sono altri vantaggi nel farlo).
Credo che questo sia specifico di Linux. Sospetto che probabilmente non sarà daiuto su nessun altro sistema operativo Unix (non testato).
Commenti
- Puoi verificare in questo modo che ha funzionato : $ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
- Significa che se imposto dimensioni illimitate con
ulimit -s unlimited
la dimensione della riga di comando sarà illimitato anche tu?
Risposta
Invece di ls */*/*/*/*.jpg
, prova:
echo */*/*/*/*.jpg | xargs ls
xargs
(1) sa qual è il numero massimo di argomenti nel sistema e interromperà il suo input standard per chiamare più volte la riga di comando specificata senza più argomenti di quel limite, qualunque esso sia (puoi anche impostarlo su un valore inferiore al massimo del sistema operativo utilizzando -n
opzione).
Per esempio, supponiamo che il limite sia di 3 argomenti e di avere cinque file. In tal caso, xargs
eseguirà ls
due volte:
-
ls 1.jpg 2.jpg 3.jpg
-
ls 4.jpg 5.jpg
Spesso è perfettamente adatto, ma non sempre – ad esempio, non puoi fare affidamento su ls
(1) ordinamento di tutte le voci correttamente, perché ogni ls
-invocazione separata ordinerà solo il sottoinsieme di voci assegnategli da xargs
.
Sebbene tu possa superare il limite come suggerito da altri, ci sarà comunque un limite – e un giorno la tua collezione JPG diventerà di nuovo troppo grande. Dovresti preparare i tuoi script per gestire un numero infinito …
Commenti
- Grazie per lidea! Questa non è una cattiva soluzione alternativa. Due avvertenze: 1. Questo non funziona con le directory e i nomi di file che hanno spazi nel nome, quindi ‘ non è un sostituto perfetto. 2. Si verificherà lo stesso problema con
Argument list too long
, ma perecho
invece dils
, sulle shell in cuiecho
non è un comando incorporato della shell? (Forse ‘ non è un problema nella maggior parte delle shell, quindi forse ‘ è irrilevante.) - Sì , i caratteri speciali nei nomi dei file sono un problema. La soluzione migliore è utilizzare
find
con il-print0
predicato e convogliarne loutput inxargs
con lopzione-0
.echo
è una shell incorporata e non soffre dei limiti della riga di comando diexec
(3). - Funziona con i comandi che prevedono largomento della variabile come ultimo parametro, ad esempio per
ls
, ma cosa faccio quando vogliomv
molti file in una singola directory, ad esmv * destdir
? Se*
restituisce ” troppi argomenti ” errore, posso ‘ per fare in qualche modoxargs
passare i percorsi come primo amv
o posso? - Controlla la pagina man per
xargs
sul tuo sistema – su FreeBSD, ad esempio,-J
ti aiuterà tu con questo compito. Se sul tuo sistema operativo non cè modo di farlo, ‘ dovrai scrivere uno script personalizzato per riordinare gli argomenti. Qualcosa come:destdir=$1; shift; mv "$@" "$destdir"
. Quindi dai questo nuovo script axargs
:.... | xargs newscript $destdir
Rispondi
Questo articolo di Linux Journal fornisce 4 soluzioni. Solo la quarta soluzione non comporta la modifica del comando:
Il metodo n. 4 prevede laumento manuale del numero di pagine allocate nel kernel per la riga di comando argomenti. Se guardi il file include / linux / binfmts.h, troverai quanto segue allinizio:
/* * 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
Per aumentare la quantità di memoria dedicato agli argomenti della riga di comando, è sufficiente fornire al valore MAX_ARG_PAGES un numero più alto. Una volta salvata questa modifica, è sufficiente ricompilare, installare e riavviare nel nuovo kernel come faresti normalmente.
Sul mio sistema di test sono riuscito a risolvere tutti i miei problemi aumentando questo valore a 64. Dopo un lungo periodo di tempo test, non ho riscontrato alcun problema dopo il passaggio. Questo è del tutto prevedibile poiché anche con
MAX_ARG_PAGES
impostato su 64, la riga di comando più lunga possibile che potrei produrre occuperebbe solo 256 KB di memoria di sistema, non molto per gli standard hardware di sistema odierni .I vantaggi del Metodo n. 4 sono evidenti. Ora puoi semplicemente eseguire il comando come faresti normalmente e si completa con successo. Gli svantaggi sono altrettanto chiari. Se aumenti la quantità di memoria disponibile alla riga di comando oltre la quantità di memoria di sistema disponibile, è possibile creare un attacco DOS sul proprio sistema e provocarne il crash. Sui sistemi multiutente in particolare, anche un piccolo aumento può avere un impatto significativo perché a ogni utente viene quindi assegnato il memoria aggiuntiva. Pertanto, esegui sempre un test approfondito nel tuo ambiente, poiché questo è il modo più sicuro per determinare se il Metodo n. 4 è unopzione praticabile per te.
Sono daccordo che la limitazione è seriamente fastidiosa.