CP: numero massimo di argomenti dei file di origine per l'utilità di copia


11

Considera che ci sono innumerevoli file in / src /

cp /src/* /dst/

Quanti file cpverranno elaborati correttamente?


2
Se l'elenco degli argomenti è troppo lungo (ricorda, ciò che * fa è espandere un elenco di tutti i file che corrispondono al glob), puoi aggirarlo usando eg IFS="\n" for file in /src/*; do mv "$file" /dst/; doneo rsync -a /src/ /dst/.
DopeGhoti,

Risposte:


18

Ciò dipende molto dal sistema e dalla versione, dal numero e dalla dimensione degli argomenti e dal numero e dalla dimensione dei nomi delle variabili di ambiente.

Tradizionalmente su Unix, il limite (come riportato da getconf ARG_MAX) era più o meno sulla dimensione cumulativa di:

  • La lunghezza delle stringhe di argomenti (inclusa la terminazione '\0')
  • La lunghezza della matrice di puntatori a tali stringhe, quindi in genere 8 byte per argomento su un sistema a 64 bit
  • La lunghezza delle stringhe di ambiente (compresa la terminazione '\0'), essendo una stringa di ambiente per convenzione qualcosa di simile var=value.
  • La lunghezza della matrice di puntatori a tali stringhe, quindi in genere 8 byte per argomento su un sistema a 64 bit

Tenendo presente che cpconta anche come argomento (è il primo argomento).

Su Linux, dipende dalla versione. Il comportamento lì è cambiato di recente dove non è più uno spazio fisso.

Controllando su Linux 3.11, getconf ARG_MAXora riporta un quarto del limite impostato sulla dimensione dello stack, o 128 kB se è inferiore a 512 kB.

( zshsintassi di seguito):

$ limit stacksize
stacksize       8MB
$ getconf ARG_MAX
2097152
$ limit stacksize 4M
$ getconf ARG_MAX
1048576

Tale limite è sulla dimensione cumulativa dell'argomento e delle stringhe di ambiente e alcune spese generali (sospetto a causa della considerazione dell'allineamento sui confini della pagina). La dimensione dei puntatori non viene presa in considerazione.

Cercando il limite, ottengo:

$ /bin/true {1..164686}
$ /bin/true {1..164687}
zsh: argument list too long: /bin/true
$ x= /bin/true {1..164686}
$ x=1 /bin/true {1..164686}
zsh: argument list too long: /bin/true

La dimensione cumulativa massima prima di rompersi in quel caso è:

$ (env _=/bin/true x=;print -l /bin/true {1..164686}) | wc -c
1044462

Ora, ciò non significa che puoi passare 1 milione di argomenti vuoti. Su un sistema a 64 bit, 1 milione di argomenti vuoti crea un elenco di puntatori di 8 MB, che sarebbe superiore alla dimensione dello stack di 4 MiB.

$ IFS=:; /bin/true ${=${(l.1000000..:.)${:-}}}
zsh: killed     /bin/true ${=${(l.1000000..:.)${:-}}}

(noterai che non è un errore E2BIG. Non sono sicuro a che punto il processo venga ucciso lì se è all'interno della execvechiamata di sistema o in seguito).

Si noti inoltre (sempre su Linux 3.11) che la dimensione massima di un singolo argomento o stringa di ambiente è 128 kB, indipendentemente dalla dimensione dello stack.

$ /bin/true ${(l.131071..a.)${:-}} # 131072 OK
$ /bin/true ${(l.131072..a.)${:-}} # 131073 not
zsh: argument list too long: /bin/true
$ /bin/true ${(l.131071..a.)${:-}} ${(l.131071..a.)${:-}} # 2x 131072 OK

Puoi condividere per favore, come hai creato il 164686numero? cioè come hai calcolato che la sequenza sarebbe stata inferiore 2097152alla dimensione ARG_MAX?
Sergiy Kolodyazhnyy,

14

Ciò dipenderà dal valore di ARG_MAX che può cambiare tra i sistemi. Per scoprire il valore per l'esecuzione del sistema (mostrando il risultato sul mio come esempio):

$ getconf ARG_MAX
2097152

Questo non ha nulla a che fare con la cptua shell, è un limite imposto dal kernel, non eseguirà i exec()comandi ( ) se i loro argomenti sono più lunghi di ARG_MAX. Pertanto, se la lunghezza dell'elenco di argomenti assegnato cpè maggiore di ARG_MAX, il cpcomando non verrà eseguito affatto.

Per rispondere alla tua domanda principale, quindi, cpnon elaborerà alcun file poiché non verrà mai eseguito con così tanti argomenti. Vorrei anche menzionare che ciò non dipende dal numero di argomenti ma dalla loro lunghezza. Probabilmente potresti avere lo stesso problema con pochissimi ma nomi di file molto lunghi.


Il modo per aggirare questi errori è eseguire il comando in un ciclo:

for file in /src/*; do cp "$file" /dst/; done

Questo significa che anche linguaggi di livello inferiore come Cpossono avere problemi con ARG_MAX e nomi di file davvero lunghi?
Harold Fischer il
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.