ฉันจะค้นหาไฟล์แล้วใช้ xargs เพื่อย้ายไฟล์ได้อย่างไร


28

ฉันต้องการค้นหาไฟล์และย้ายไฟล์

ฉันสามารถค้นหาไฟล์ด้วย:

$ find /tmp/ -ctime -1 -name x*

ฉันพยายามย้ายพวกเขาไปยัง~/playไดเรกทอรีของฉันด้วย:

$ find /tmp/ -ctime -1 -name x* | xargs mv ~/play/

แต่นั่นไม่ได้ผล mv ต้องมีสองอาร์กิวเมนต์
ไม่แน่ใจว่าจะอ้างอิงรายการปัจจุบันของ xargs (หรือวิธี) ในคำสั่ง mv หรือไม่


3
ทำไม? คุณสามารถใช้ตัวยึดตำแหน่งด้วย-I: find . | xargs -I'{}' mv '{}' ~/play/แต่ตามที่มนุษย์บอกว่า“ โดยนัย-xและ-L 1” ดังนั้นจึงไม่ได้ประโยชน์ ควรทำให้ง่ายขึ้นและดีกว่าfind . -exec mv '{}' ~/play/ \;
manatwork

กรุณาโพสต์เป็นคำตอบที่จะเห็นคะแนนโหวตถ้าคุณจะไม่คิด :)
ไมเคิลแรนต์

เพิ่งถามเหตุผลของคุณเพราะฉันมีความรู้สึกว่าฉันไม่ได้รับจุด ถ้า Drav Sloan เพิ่มหมายเหตุลงบนตัวเลือกโดยนัยคำตอบของเขาจะดีเท่าที่ฉันเขียนได้ดีที่สุด ดังนั้นควรไปด้วยดีกว่า
จัดการ

สำเนาที่เป็นไปได้ของรูปแบบการค้นหาและการย้าย
slm

@manatwork ผมได้แก้ไขคำตอบของฉันที่จะสะท้อนให้เห็นถึงจุดเหล่านั้น duder :)
Drav โลน

คำตอบ:


43

ดูคำตอบของ Stephane สำหรับวิธีที่ดีที่สุดลองดูที่คำตอบของฉันด้วยเหตุผลที่จะไม่ใช้วิธีแก้ปัญหาที่ชัดเจนกว่านี้ (และเหตุผลที่ทำไมมันถึงไม่มีประสิทธิภาพมากที่สุด)

คุณสามารถใช้-Iตัวเลือกของxargs:

find /tmp/ -ctime -1 -name "x*" | xargs -I '{}' mv '{}' ~/play/

ซึ่งทำงานในกลไกคล้ายกับและfind {}ฉันจะเสนอราคา-nameอาร์กิวเมนต์ของคุณ(เนื่องจากไฟล์ที่เริ่มต้นด้วยxในไดเรกทอรีปัจจุบันจะเป็นไฟล์ขุ่นเคืองและส่งผ่านเป็นอาร์กิวเมนต์เพื่อค้นหา - ซึ่งจะไม่ให้พฤติกรรมที่คาดหวัง!)

อย่างไรก็ตามตามที่ชี้ให้เห็นโดย manatwork ตามรายละเอียดในxargsman page:

   -I replace-str
          Replace occurrences of replace-str in the initial-arguments with
          names read from standard input.  Also, unquoted  blanks  do  not
          terminate  input  items;  instead  the  separator is the newline
          character.  Implies -x and -L 1.

สิ่งสำคัญที่ควรทราบคือ-L 1หมายความว่าจะมีการประมวลผลเอาต์พุตเพียงบรรทัดเดียวfindในแต่ละครั้ง ซึ่งหมายความว่านั่นคือ syntactically เหมือนกับ:

find /tmp/ -ctime -1 -name "x*" -exec mv '{}' ~/play/

(ซึ่งดำเนินการmvการดำเนินการเดียวสำหรับแต่ละไฟล์)

แม้การใช้-0อาร์กิวเมนต์GNU xargs และfind -print0อาร์กิวเมนต์ทำให้เกิดลักษณะการทำงานที่เหมือนกัน-I- นี่คือclone()กระบวนการสำหรับแต่ละไฟล์mv:

find . -name "x*" -print0 | strace xargs -0 -I '{}' mv '{}' /tmp/other

.
.
read(0, "./foobar1/xorgslsala11\0./foobar1"..., 4096) = 870
mmap(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =     0x7fbb82fad000
open("/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=26066, ...}) = 0
mmap(NULL, 26066, PROT_READ, MAP_SHARED, 3, 0) = 0x7fbb82fa6000
close(3)                                = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,         child_tidptr=0x7fbb835af9d0) = 661
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 661
--- SIGCHLD (Child exited) @ 0 (0) ---
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,         child_tidptr=0x7fbb835af9d0) = 662
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 662
--- SIGCHLD (Child exited) @ 0 (0) ---
.
.
.

ที่ถือว่าชื่อไฟล์ไม่มีบรรทัดใหม่อัญประกาศเดี่ยวอัญประกาศคู่หรืออักขระเครื่องหมายทับขวา
Stéphane Chazelas

17

ด้วยเครื่องมือ GNU:

find /tmp/ -ctime -1 -name 'x*' -print0 |
  xargs -r0 mv -t ~/play/

-t( --target) ตัวเลือกที่ GNU เฉพาะ -print0, -r, -0ในขณะที่ไม่ได้มาตรฐานและมีต้นกำเนิดใน GNU นอกจากนี้ยังพบในการใช้งานอื่น ๆ เช่นในบาง BSDs

POSIXly:

find /tmp/ -ctime -1 -name 'x*' -exec sh -c '
  exec mv "$@" ~/play/' sh {} +

ทั้งเรียกใช้mvคำสั่งน้อยตามความจำเป็นและทำงานอักขระใด ๆ ที่ชื่อไฟล์อาจมี GNU หนึ่งอาจมีข้อได้เปรียบที่findคอยค้นหาไฟล์ในขณะที่mvเริ่มเคลื่อนย้ายแบตช์แรก

ระวังว่าไฟล์และไดเรกทอรีทั้งหมดจะจบลงในไดเรกทอรีเดียวระวัง clashes หากหลาย ๆ ไฟล์ในไดเรกทอรีต่างมีชื่อเดียวกัน


โซลูชันนี้ทำงานได้ดีขึ้นมากเนื่องจากเรียกใช้mvหนึ่งครั้งสำหรับอาร์กิวเมนต์ทั้งหมด (หรือทั้งหมด-Lหรือ-nถ้ามีให้) มิฉะนั้นการเรียกmvแต่ละไฟล์จะเก่า (และช้า) อย่างรวดเร็ว
r2evans

1

บางทีคำสั่งนี้อาจเป็นไปได้ในตอนนี้และไม่ได้กลับมาในปี 2013 แต่ก็ใช้ได้ดีสำหรับฉัน:

ls pattern* | xargs mv -t DESTINATION/

-tทำให้คีย์โฟลเดอร์ปลายทางแรกพ้นmvคำสั่งที่จะมีข้อโต้แย้งที่ผ่านมาทั้งหมดเป็นเพียงไฟล์ที่จะย้าย


1
นี่เป็นทางออกที่ง่ายที่สุดที่ทำงานให้ฉัน
ptetteh227

0

คุณสามารถลองด้วยคำสั่งด้านล่างและทดสอบและมันทำงานได้ดี

find /tmp/ -ctime -1 -type f -name "x*" -exec mv -t ~/play/ {} \;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.