CP: อาร์กิวเมนต์หมายเลขไฟล์ต้นฉบับสูงสุดสำหรับโปรแกรมอรรถประโยชน์การคัดลอก


11

พิจารณาว่ามีไฟล์นับไม่ถ้วนภายใต้ / src /

cp /src/* /dst/

cpสามารถประมวลผลไฟล์ได้สำเร็จกี่ไฟล์?


2
หากรายการอาร์กิวเมนต์ยาวเกินไป (จำสิ่งที่ * ไม่สามารถขยายไปยังรายชื่อของไฟล์ทั้งหมดที่ตรงกับ glob ที่) คุณจะได้รับรอบโดยใช้เช่นหรือIFS="\n" for file in /src/*; do mv "$file" /dst/; done rsync -a /src/ /dst/
DopeGhoti

คำตอบ:


18

ขึ้นอยู่กับระบบและเวอร์ชันเป็นอย่างมากตามจำนวนและขนาดของอาร์กิวเมนต์และจำนวนและขนาดของชื่อตัวแปรสภาพแวดล้อม

ตามธรรมเนียมบน Unix ขีด จำกัด (ตามที่รายงานโดยgetconf ARG_MAX) มีขนาดเพิ่มขึ้นหรือน้อยลงตาม:

  • ความยาวของสตริงอาร์กิวเมนต์ (รวมถึงการยกเลิก'\0')
  • ความยาวของอาร์เรย์ของพอยน์เตอร์กับสตริงเหล่านั้นดังนั้นโดยทั่วไปแล้ว 8 ไบต์ต่ออาร์กิวเมนต์บนระบบ 64 บิต
  • ความยาวของสตริงสภาพแวดล้อม (รวมทั้งยุติ'\0') var=valueสตริงสภาพแวดล้อมที่เป็นอะไรบางอย่างเช่นการประชุม
  • ความยาวของอาร์เรย์ของพอยน์เตอร์กับสตริงเหล่านั้นดังนั้นโดยทั่วไปแล้ว 8 ไบต์ต่ออาร์กิวเมนต์บนระบบ 64 บิต

จำไว้ว่าcpยังนับเป็นอาร์กิวเมนต์ (เป็นอาร์กิวเมนต์แรก)

บน Linux มันขึ้นอยู่กับเวอร์ชั่น พฤติกรรมที่มีการเปลี่ยนแปลงเมื่อเร็ว ๆ นี้ที่มันไม่ได้เป็นพื้นที่คงที่อีกต่อไป

ตรวจสอบบน Linux 3.11 getconf ARG_MAXตอนนี้รายงานหนึ่งในสี่ของขีด จำกัด ที่ตั้งค่าไว้กับขนาดสแต็กหรือ 128kiB หากน้อยกว่า 512kiB)

( zshไวยากรณ์ด้านล่าง):

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

ขีด จำกัด นั้นขึ้นอยู่กับขนาดสะสมของอาร์กิวเมนต์และสตริงสภาพแวดล้อมและค่าใช้จ่ายบางส่วน (ฉันสงสัยว่าเนื่องจากการพิจารณาการจัดตำแหน่งในขอบเขตหน้า) ขนาดของพอยน์เตอร์ไม่ได้ถูกนำมาพิจารณา

ค้นหาขีด จำกัด ฉันได้รับ:

$ /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

ขนาดสะสมสูงสุดก่อนแตกในกรณีนี้คือ:

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

ตอนนี้ไม่ได้หมายความว่าคุณสามารถผ่านอาร์กิวเมนต์ที่ว่าง 1 ล้าน บนระบบ 64 บิตอาร์กิวเมนต์ว่างเปล่า 1 ล้านรายการสร้างรายการตัวชี้ขนาด 8MB ซึ่งจะสูงกว่าขนาดสแต็กของฉันที่ 4MiB

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

(คุณจะสังเกตเห็นว่าไม่ใช่ข้อผิดพลาด E2BIG ฉันไม่แน่ใจว่าจะมีกระบวนการใดถูกฆ่าที่จุดนั้นแม้ว่าจะอยู่ในการexecveเรียกของระบบหรือหลังจากนั้น)

โปรดทราบว่า (ยังคงอยู่บน Linux 3.11) ว่าขนาดสูงสุดของอาร์กิวเมนต์เดียวหรือสตริงสภาพแวดล้อมคือ 128kiB โดยไม่คำนึงถึงขนาดสแต็ก

$ /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เลขอย่างไร นั่นคือวิธีที่คุณคำนวณลำดับที่จะอยู่ภายใต้2097152ขนาด ARG_MAX?
Sergiy Kolodyazhnyy

14

ที่จะขึ้นอยู่กับค่าของ ARG_MAX ซึ่งสามารถเปลี่ยนระหว่างระบบ หากต้องการทราบค่าสำหรับการทำงานของระบบของคุณ (แสดงผลการขุดเป็นตัวอย่าง):

$ getconf ARG_MAX
2097152

นี้มีอะไรจะทำอย่างไรกับcpหรือเปลือกของคุณมันเป็นข้อ จำกัด ที่กำหนดโดยเคอร์เนลก็จะไม่ดำเนินการ ( exec()) ARG_MAXคำสั่งถ้าขัดแย้งของพวกเขามีความยาวมากกว่า ดังนั้นหากความยาวของรายการอาร์กิวเมนต์ที่คุณให้cpมากกว่า ARG_MAX cpคำสั่งจะไม่ทำงานเลย

เพื่อตอบคำถามหลักของคุณแล้วcpจะไม่ประมวลผลไฟล์ใด ๆ เนื่องจากจะไม่มีการดำเนินการกับอาร์กิวเมนต์จำนวนมาก ฉันควรพูดถึงว่าสิ่งนี้ไม่ได้ขึ้นอยู่กับจำนวนอาร์กิวเมนต์ แต่ขึ้นอยู่กับความยาว คุณอาจมีปัญหาเดียวกันกับชื่อไฟล์น้อยมาก แต่ยาวมาก


วิธีการแก้ไขข้อผิดพลาดเหล่านี้คือการเรียกใช้คำสั่งของคุณแบบวนซ้ำ:

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

นี่หมายความว่าแม้แต่ภาษาระดับต่ำกว่าอย่างเช่นCสามารถมีปัญหากับ ARG_MAX และชื่อไฟล์ที่ยาวมาก ๆ ?
Harold Fischer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.