Yanıtlar:
Bu büyük ölçüde sisteme ve sürüme, bağımsız değişkenlerin sayısına ve boyutuna ve ortam değişkeni adlarının sayısına ve boyutuna bağlıdır.
Geleneksel olarak Unix'te, sınır (tarafından bildirildiği gibi getconf ARG_MAX
), aşağıdakilerin kümülatif boyutunda aşağı yukarı idi:
'\0'
)'\0'
), bir ortam dizesi konvansiyona benzer bir şeydir var=value
.Hatırda tutarak cp
bağımsız değişken olarak da sayıları (ilk argümandır).
Linux'ta, sürüme bağlıdır. Oradaki davranış, artık sabit bir alan olmadığı yerde değişti.
Linux 3.11 üzerinde kontrol, getconf ARG_MAX
artık yığın boyutunda belirlenen sınırın dörtte birini veya 512kiB'den küçükse 128kiB'yi bildiriyor).
( zsh
aşağıdaki sözdizimi):
$ limit stacksize
stacksize 8MB
$ getconf ARG_MAX
2097152
$ limit stacksize 4M
$ getconf ARG_MAX
1048576
Bu sınır, argümanın ve ortam dizgilerinin kümülatif boyutu ve bazı ek yükler üzerindedir (sayfa sınırlarındaki hizalama nedeniyle şüpheleniyorum). İşaretçilerin boyutu dikkate alınmaz.
Sınırı ararken, şunu elde ederim:
$ /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
Bu durumda kırılmadan önceki maksimum kümülatif boyut:
$ (env _=/bin/true x=;print -l /bin/true {1..164686}) | wc -c
1044462
Artık bu, 1 milyon boş argüman aktarabileceğiniz anlamına gelmiyor. 64 bit sistemde, 1 milyon boş argüman 8 MB'lık bir işaretçi listesi oluşturur, bu da 4MiB yığın boyutumun üstünde olur.
$ IFS=:; /bin/true ${=${(l.1000000..:.)${:-}}}
zsh: killed /bin/true ${=${(l.1000000..:.)${:-}}}
(bunun bir E2BIG hatası olmadığını fark edeceksiniz. execve
Sistem çağrısında veya daha sonra olsa, işlemin orada hangi noktada öldürüldüğünden emin değilim ).
Ayrıca (hala Linux 3.11'de), tek bir argümanın veya ortam dizesinin maksimum boyutunun, yığının boyutuna bakılmaksızın 128kiB olduğunu unutmayın.
$ /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
164686
numarayı nasıl buldun ? yani bu dizinin 2097152
ARG_MAX boyutunun altında olacağını nasıl hesapladınız ?
Bu, sistemler arasında değişebilen ARG_MAX değerine bağlı olacaktır. Sistem çalıştırmanızın değerini bulmak için (sonucu benimki örnek olarak gösteren):
$ getconf ARG_MAX
2097152
Bunun cp
veya kabuğunuzla ilgisi yoktur , çekirdek tarafından dayatılan bir sınırdır exec()
, argümanları daha uzunsa ( ) komutlarını yürütmez ARG_MAX
. Dolayısıyla, verdiğiniz bağımsız değişken listesinin cp
uzunluğu ARG_MAX'tan büyükse, cp
komut hiç çalışmaz.
O zaman ana sorunuzu cevaplamak için cp
hiçbir dosya işlenmeyecektir çünkü hiçbir zaman bu kadar çok argümanla yürütülmeyecektir. Ayrıca bunun argüman sayısına değil uzunluğuna bağlı olduğunu da belirtmeliyim. Muhtemelen çok az ama çok uzun dosya adlarıyla aynı sorunu yaşayabilirsiniz.
Bu hataların üstesinden gelmenin yolu, komutunuzu bir döngüde çalıştırmaktır:
for file in /src/*; do cp "$file" /dst/; done
C
ARG_MAX ve gerçekten uzun dosya adlarıyla ilgili sorunlara sahip olabileceği anlamına mı geliyor ?
IFS="\n" for file in /src/*; do mv "$file" /dst/; done
Veyarsync -a /src/ /dst/
.