หา + xargs: อาร์กิวเมนต์ยาวเกินไป


21

ฉันมีสายเหมือนดังต่อไปนี้:

find /foo/bar -name '*.mp4' -print0 | xargs -i {} -0 mv -t /some/path {}

แต่ฉันได้รับข้อผิดพลาดต่อไปนี้:

xargs: argument line too long

ฉันสับสน. การใช้ที่xargsควรจะช่วยอย่างแม่นยำกับปัญหานี้ไม่ใช่หรือ

หมายเหตุ:ฉันรู้ว่าฉันสามารถใช้เทคโนโลยี-execในการค้นหา แต่ฉันต้องการที่จะเข้าใจว่าทำไมข้างต้นล้มเหลวเนื่องจากความเข้าใจของฉันคือที่xargsควรรู้วิธีการแยกอินพุตเป็นขนาดที่จัดการได้เพื่อโต้แย้งว่ามันทำงาน สิ่งนี้ไม่จริงหรือ

นี่คือทั้งหมดที่มี zsh

คำตอบ:


11

ดีสำหรับสิ่งหนึ่งที่-iสวิตช์เลิกใช้แล้ว:

-i[replace-str]
     This  option  is a synonym for -Ireplace-str if replace-str is specified. 
     If the replace-str argument is missing, the effect is the same as -I{}. 
     This option is deprecated; use -I instead.

ดังนั้นเมื่อฉันเปลี่ยนคำสั่งของคุณเป็นแบบนี้มันทำงานได้:

$ find /foo/bar -name '*.mp4' -print0 | xargs -I{} -0 mv -t /some/path {}

ตัวอย่าง

$ find . -print0 | xargs -I{} -0 echo {}
.
./.sshmenu
./The GIT version control system.html
./.vim_SO
./.vim_SO/README.txt
./.vim_SO/.git
./.vim_SO/.git/objects
./.vim_SO/.git/objects/pack
./.vim_SO/.git/objects/pack/pack-42dbf7fe4a9b431a51da817ebf58cf69f5b7117b.idx
./.vim_SO/.git/objects/pack/pack-42dbf7fe4a9b431a51da817ebf58cf69f5b7117b.pack
./.vim_SO/.git/objects/info
./.vim_SO/.git/refs
./.vim_SO/.git/refs/tags
...

การใช้ -I{}

ไม่ควรใช้วิธีนี้ตั้งแต่เริ่มสร้างคำสั่งนี้:

$ find -print0 ... | xargs -I{} -0 ...

โดยปริยายจะเปิดสวิทช์เหล่านี้เพื่อxargs, และ-x -L 1การ-L 1กำหนดค่าxargsเพื่อให้มันเรียกคำสั่งที่คุณต้องการให้เรียกใช้ไฟล์ในแบบเดียว

ดังนั้นนี่จะเป็นการทำลายจุดประสงค์ของการใช้xargsที่นี่เพราะถ้าคุณให้ไฟล์ 1,000 ไฟล์มันจะทำงานmvคำสั่ง 1,000 ครั้ง

ดังนั้นฉันควรใช้วิธีการแบบไหน?

คุณสามารถทำได้โดยใช้ xargs ดังนี้:

$ find /foot/bar/ -name '*.mp4' -print0 | xargs -0 mv -t /some/path

หรือเพียงแค่ได้พบทำมันทั้งหมด:

$ find /foot/bar/ -name '*.mp4' -exec mv -t /some/path {} +

ขอบคุณ! เมื่อใดที่คุณบอกว่า"This approach shouldn't be used"ควรใช้วิธีการใดแทน จะ"find /foot/bar/ -name '*.csv' -print0 | xargs -0 mv -t some_dir'"เป็นทางออกที่ดีกว่า ถ้าเป็นเช่นนั้นว่าไม่xargsทราบว่าในกรณีนี้ที่อยู่ในmvคำสั่งไปยังฟีดในข้อโต้แย้งที่จะได้รับจากท่อ? (มันมักจะวางพวกเขาครั้งสุดท้าย?)
Amelio Vazquez-Reina

@ user815423426 - ทำมันมีเพียงfind ... -exec ...วิธีที่ดีกว่าหรือถ้าคุณต้องการที่จะใช้เป็นดีเกินไป ใช่มันทำให้พวกเขาล่าสุด นั่นเป็นเหตุผลที่วิธีการที่ต้องการ xargsfind ... | xargs ... mv -t ...-t
slm

5

ตัวเลือก-iใช้อาร์กิวเมนต์ตัวเลือก เนื่องจากคุณใส่ช่องว่างหลังจากที่-iมีการโต้แย้งที่จะไม่มี-iตัวเลือกจึงตามมา-0ไม่ได้เป็นตัวเลือกให้xargsแต่ที่สองของ 6 {} -0 mv -t /some/path {}ตัวถูกดำเนิน

มีเพียงตัวเลือก-iเท่านั้น xargs คาดว่าจะมีรายการชื่อไฟล์ที่คั่นด้วยการขึ้นบรรทัดใหม่ เนื่องจากอาจไม่มีการขึ้นบรรทัดใหม่ในอินพุต xargs จึงได้รับสิ่งที่ดูเหมือนชื่อไฟล์ขนาดใหญ่ (ที่มีไบต์ว่างฝังอยู่ แต่ xargs ไม่ได้ตรวจสอบว่า) สตริงเดี่ยวนี้ที่มีเอาต์พุตทั้งหมดfindยาวกว่าความยาวบรรทัดคำสั่งสูงสุดดังนั้นข้อผิดพลาด“ บรรทัดคำสั่งยาวเกินไป”

คำสั่งของคุณจะได้ทำงานร่วมกับแทน-i{} -i {}หรือคุณอาจใช้-I {}: -Iคล้ายกับ-iแต่รับอาร์กิวเมนต์ที่จำเป็นดังนั้นอาร์กิวเมนต์ถัดไปที่ส่งผ่านไปยังจะxargsถูกใช้เป็นอาร์กิวเมนต์ของ-Iตัวเลือก จากนั้นอาร์กิวเมนต์หลังจากนั้นจะ-0ถูกตีความว่าเป็นตัวเลือกและอื่น ๆ

อย่างไรก็ตามคุณไม่ควรใช้-I {}เลย การใช้-Iมีสามเอฟเฟกต์:

  • -Iปิดการประมวลผลคำพูดซึ่ง-0ทำไปแล้ว
  • -Iเปลี่ยนสตริงที่จะแทนที่ แต่{}เป็นค่าเริ่มต้น
  • -Iทำให้คำสั่งถูกเรียกใช้งานแยกต่างหากสำหรับแต่ละเร็กคอร์ดอินพุตซึ่งไม่มีประโยชน์ที่นี่เนื่องจากคำสั่งของคุณ ( mv -t) มีจุดประสงค์เพื่อจัดการกับไฟล์หลายไฟล์ต่อการเรียกใช้

ทั้งหยด-Iและ-iรวมกัน

find /foo/bar -name '*.mp4' -print0 | xargs -0 mv -t /some/path {}

หรือวาง xargs และใช้-exec:

find /foo/bar -name '*.mp4' -exec mv -t /some/path {} +

0

ลองใช้ bash for loop:

for FILE in *.mp4 ; do rm $FILE ; done

หรือหากคุณต้องการดูว่าเกิดอะไรขึ้น:

for FILE in *.mp4 ; do echo Removing $FILE ; rm $FILE ; done

0

หากคุณกำลังเห็นนี้ในขณะที่ใช้เปลือกปลา
สิ่งนี้เกี่ยวข้องกับวิธีที่ปลาขยายสายอักขระการแทนที่{}

หากคุณกำลังใช้ปลาคุณต้องหลบหนีจากสายการเปลี่ยน \{\}

| xargs -I \{\} echo \{\}

หรือใช้สตริงการแทนที่ที่แตกต่างกัน

| xargs -I ! echo !
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.