Câu trả lời:
Điều đó phụ thuộc rất lớn vào hệ thống và phiên bản, vào số lượng và kích thước của các đối số cũng như số lượng và kích thước của tên biến môi trường.
Theo truyền thống trên Unix, giới hạn (như được báo cáo bởi getconf ARG_MAX
) ít nhiều về kích thước tích lũy của:
'\0'
)'\0'
), một chuỗi môi trường theo quy ước tương tự var=value
.Ghi nhớ rằng cp
cũng được tính là một đối số (là đối số đầu tiên).
Trên Linux, nó phụ thuộc vào phiên bản. Hành vi ở đó đã thay đổi gần đây khi nó không còn là một không gian cố định.
Kiểm tra trên Linux 3.11, getconf ARG_MAX
hiện báo cáo một phần tư giới hạn được đặt trên kích thước ngăn xếp hoặc 128kiB nếu đó nhỏ hơn 512kiB).
( zsh
cú pháp dưới đây):
$ limit stacksize
stacksize 8MB
$ getconf ARG_MAX
2097152
$ limit stacksize 4M
$ getconf ARG_MAX
1048576
Giới hạn đó nằm ở kích thước tích lũy của đối số và chuỗi môi trường và một số chi phí chung (tôi nghi ngờ do xem xét căn chỉnh trên ranh giới trang). Kích thước của con trỏ không được tính đến.
Tìm kiếm giới hạn, tôi nhận được:
$ /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
Kích thước tích lũy tối đa trước khi phá vỡ trong trường hợp đó là:
$ (env _=/bin/true x=;print -l /bin/true {1..164686}) | wc -c
1044462
Bây giờ, điều đó không có nghĩa là bạn có thể vượt qua 1 triệu đối số trống. Trên hệ thống 64 bit, 1 triệu đối số trống tạo danh sách con trỏ 8 MB, cao hơn kích thước ngăn xếp 4MiB của tôi.
$ IFS=:; /bin/true ${=${(l.1000000..:.)${:-}}}
zsh: killed /bin/true ${=${(l.1000000..:.)${:-}}}
(bạn sẽ nhận thấy đó không phải là lỗi E2BIG. Tôi không chắc chắn tại thời điểm nào quá trình sẽ bị giết ở đó nếu nó nằm trong execve
cuộc gọi hệ thống hoặc sau này).
Cũng lưu ý (vẫn trên Linux 3.11) rằng kích thước tối đa của một đối số hoặc chuỗi môi trường là 128kiB, bất kể kích thước của ngăn xếp.
$ /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
số? tức là làm thế nào bạn tính được chuỗi đó sẽ có 2097152
kích thước ARG_MAX?
Điều đó sẽ phụ thuộc vào giá trị của ARG_MAX có thể thay đổi giữa các hệ thống. Để tìm ra giá trị cho hệ thống của bạn chạy (hiển thị kết quả trên ví dụ của tôi):
$ getconf ARG_MAX
2097152
Điều này không có gì để làm với cp
hoặc shell của bạn, nó là một giới hạn được áp đặt bởi kernel, nó sẽ không thực thi exec()
các lệnh ( ) nếu các đối số của chúng dài hơn ARG_MAX
. Vì vậy, nếu độ dài của danh sách đối số bạn đã cung cấp cp
lớn hơn ARG_MAX, cp
lệnh sẽ hoàn toàn không chạy.
Để trả lời câu hỏi chính của bạn sau đó, cp
sẽ xử lý không có tệp nào vì nó sẽ không bao giờ được thực thi với quá nhiều đối số. Tôi cũng nên đề cập rằng điều này không phụ thuộc vào số lượng đối số mà phụ thuộc vào độ dài của chúng. Bạn có thể hình dung có cùng một vấn đề với rất ít tên tệp rất dài.
Cách khắc phục các lỗi này là chạy lệnh của bạn trong một vòng lặp:
for file in /src/*; do cp "$file" /dst/; done
C
có thể có vấn đề với ARG_MAX và tên tệp thực sự dài?
IFS="\n" for file in /src/*; do mv "$file" /dst/; done
hoặcrsync -a /src/ /dst/
.