Elenco degli argomenti troppo lungo per ls


48

Ottengo il seguente errore quando provo in ls *.txt | wc -luna directory che contiene molti file:

-bash: /bin/ls: Argument list too long

La soglia di questo "Elenco argomenti" dipende dalla distro o dalle specifiche del computer? Di solito, convoglio il risultato di un risultato così grande ad altri comandi ( wc -lad esempio), quindi non mi preoccupo dei limiti del terminale.


6
Ciò conta come output dell'analisils , che è una cattiva idea, quindi meglio evitarlo. Per il conteggio vedi Qual è il modo migliore per contare il numero di file in una directory? , per una soluzione complicata vedi perché for loop non genera l'errore "argomento troppo lungo"? .
arte

@manatwork Sì, ho visto anche quelle domande. Mi chiedo solo un modo migliore per utilizzare o reindirizzare un output lungo da un comando in un modo più generale.

puoi usare getconf ARG_MAX per ottenere il limite sulla maggior parte dei sistemi basati su unix
Prasanth,

Risposte:


49

L' elenco degli argomenti dei messaggi di errore troppo lungo deriva dal * di ls *.txt.

Questo limite è una sicurezza sia per i programmi binari che per il tuo kernel. Vedrai in questa pagina maggiori informazioni a riguardo, e come viene utilizzato e calcolato.

Non esiste tale limite per le dimensioni del tubo. Quindi puoi semplicemente emettere questo comando:

find -type f -name '*.txt'  | wc -l

NB: Su Linux moderno, i caratteri strani nei nomi dei file (come le nuove righe) verranno salvati con strumenti come lso find, ma comunque visualizzati da * . Se sei su un vecchio Unix, avrai bisogno di questo comando

find -type f -name '*.txt' -exec echo \;  | wc -l

NB2: Mi chiedevo come si possa creare un file con una nuova riga nel suo nome. Non è così difficile, una volta che conosci il trucco:

touch "hello
world"

1
L'ho modificato leggermente per funzionare nel caso in cui ci siano nomi di file con nuove righe. È inoltre possibile aggiungere a -maxdepth 1se non si intende contare i file nelle sottodirectory.
Shawn J. Goff,

Non hai bisogno del -exec echo \;.
Mikel,

@ ShawnJ.Goff L'ho provato. Non c'è bisogno di `echo` nella versione corrente di GNU find
Coren,

@Coren @Mikel - non tutti hanno GNU find. Gli findsu OS X e sui sistemi busybox-based, e direi qualsiasi spettacoli di sistema basati su BSD il nome del file con una nuova riga in esso, che avrebbe pasticciare con il conteggio.
Shawn J. Goff,

Eh? wc -lsta contando le nuove righe. Quindi vogliamo che abbia nuove linee.
Mikel,

11

Dipende principalmente dalla tua versione del kernel Linux.

Dovresti riuscire a vedere il limite del tuo sistema eseguendolo

getconf ARG_MAX

che indica il numero massimo di byte che una riga di comando può avere dopo essere stata espansa dalla shell.

In Linux <2.6.23, il limite è generalmente di 128 KB.

In Linux> = 2.6.25, il limite è di 128 KB o 1/4 della dimensione dello stack (vedi ulimit -s), a seconda di quale sia maggiore.

Vedi la pagina man execve (2) per tutti i dettagli.


Sfortunatamente, le tubazioni ls *.txtnon risolveranno il problema, perché il limite è nel sistema operativo, non nella shell.

La shell espande il *.txt, quindi tenta di chiamare

exec("ls", "a.txt", "b.txt", ...)

e hai così tanti file corrispondenti *.txtche stai superando il limite di 128 KB.

Dovrai fare qualcosa del genere

find . -maxdepth 1 -name "*.txt" | wc -l

anziché.

(E vedi sotto i commenti di Shawn J. Goff sui nomi dei file che contengono nuove righe.)


Ci scusiamo per non aver potuto votare una risposta. Hai bisogno di più reputazione. :( Grazie a tutti !!

Ci può spiegare quello che il .e la -maxdepth 1media nell'ultima riga? Grazie! : D
Guilherme Salomé,

2
@ GuilhermeSalomé .significa directory corrente, -maxdepth 1significa che non cerca nelle sottodirectory. Questo doveva corrispondere agli stessi file di *.txt.
Mikel,

9

Un'altra soluzione alternativa:

ls | grep -c '\.txt$'

Sebbene lsproduca più output di quanto ls *.txtproduca (o tenti di produrre), non si imbatte nel problema "argomento troppo lungo", perché non si passa alcun argomento ls. Si noti che grepaccetta un'espressione regolare anziché un modello di corrispondenza dei file.

Potresti voler usare:

ls -U | grep -c '\.txt$'

(supponendo che la tua versione di lssupporti questa opzione). Questo dice di lsnon ordinare il suo output, il che potrebbe far risparmiare tempo e memoria - e in questo caso l'ordine non ha importanza, poiché stai solo contando i file. Le risorse impiegate per ordinare l'output di solito non sono significative, ma in questo caso sappiamo già che hai un numero molto elevato di *.txtfile.

E dovresti considerare di riorganizzare i tuoi file in modo da non averne così tanti in una singola directory. Questo può o non può essere fattibile.


1

MAX_ARG_PAGES sembra essere un parametro del kernel. L'uso di finded xargsè una combinazione tipica per affrontare questo limite, ma non sono sicuro che funzionerà wc.

Il piping dell'output di find . -name \*\.txtun file e il conteggio delle righe in quel file dovrebbero servire da soluzione alternativa.


Puoi fare qualsiasi cosa con lsl'output, non risolverlo. Fintanto che il carattere jolly * .txt viene espanso oltre il limite, fallirà anche prima di avviare lse generare qualsiasi output.
arte

Vero, ho aggiornato la mia risposta.
Bram,

Meglio. Ma per renderlo un sostituto lsdevi specificare -maxdepth 1di evitare la scansione ricorsiva delle sottodirectory.
arte

Ci scusiamo per non aver potuto votare una risposta. Hai bisogno di più reputazione. :(

0

Questo potrebbe essere sporco ma funziona per le mie esigenze e nell'ambito delle mie competenze. Non penso che si esibisca molto rapidamente, ma mi ha permesso di andare avanti con la mia giornata.

ls | grep jpg | <something>

Stavo ottenendo un elenco di 90.000 di jpg lunghi e li convogliavo su avconv per generare un timelapse.

In precedenza utilizzavo ls * .jpg | avconv prima di imbattermi in questo problema.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.