คัดลอกไฟล์ทั้งหมดภายในไดเรกทอรีย่อยและเปลี่ยนชื่อแทนการเขียนทับ


4

ฉันมีรูปภาพจำนวนหนึ่งในไดเรกทอรีย่อยของไดเรกทอรีอื่นซึ่งฉันต้องการคัดลอกไปยังไดเรกทอรีเดียวเพื่อให้ภาพทั้งหมดอยู่ในที่เดียว

หลังจากการค้นหาเล็กน้อยฉันพบแล้วแก้ไขบางสิ่งเพื่อสร้างคำสั่งนี้:

find . -name "z*.jpg" -exec cp '{}' ~/Extracted/ \;

ดูเหมือนว่าจะใช้ได้ แต่ฉันพบว่าภาพที่มีชื่อเดียวกันจะถูกเขียนทับดังนั้นฉันจึงทำสิ่งนี้:

find . -name "z*.jpg" -exec cp -n '{}' ~/Extracted/ \;

แต่ตอนนี้ภาพที่มีชื่อเดียวกันจะถูกละเว้น

ฉันสามารถทำเช่นนี้ได้ดังนั้นทุกภาพจะถูกคัดลอกและภาพที่มีชื่อเดียวกันจะถูกเปลี่ยนชื่อหรือไม่?

คำตอบ:


6

GNUcp(1)มีตัวเลือกสำรอง:

cp --backup SOURCE [SOURCE...] [DESTINATION]

นี่คือเอฟเฟกต์ต่อไปนี้ซึ่งสามารถควบคุมได้ด้วยตัวเลือกอื่นดังที่อธิบายไว้ในหน้าคู่มือของcp(1):

--backup[=CONTROL]
          make a backup of each existing destination file

-b     like --backup but does not accept an argument

-S, --suffix=SUFFIX
          override the usual backup suffix

คำต่อท้ายสำรอง~เว้นแต่กำหนดด้วยหรือ--suffix SIMPLE_BACKUP_SUFFIXวิธีการควบคุมเวอร์ชันอาจถูกเลือกผ่าน--backupตัวเลือกหรือผ่านVERSION_CONTROLตัวแปรสภาพแวดล้อม นี่คือค่า:

  • none, off: ไม่ทำการสำรองข้อมูล (แม้ว่า--backupจะได้รับ)
  • numbered, t: ทำการสำรองข้อมูลที่มีหมายเลข
  • existing, nil: กำหนดหมายเลขหากมีการสำรองข้อมูลที่มีหมายเลขเป็นอย่างอื่น
  • simple, never: ทำการสำรองข้อมูลอย่างง่ายเสมอ

ตัวอย่าง

cp --backup=existing --suffix=.orig ~/Music/* ~/Videos

นี้จะคัดลอกไฟล์ทั้งหมดในการ~/Music ~/Videosหากไฟล์ที่มีชื่อเดียวกันมีอยู่ที่ปลายทางไฟล์นั้นจะถูกเปลี่ยนชื่อโดยการต่อท้าย.origชื่อเป็นการสำรองข้อมูล หากไฟล์ที่มีชื่อเดียวกับการสำรองข้อมูลมีอยู่การสำรองข้อมูลจะถูกเปลี่ยนชื่อแทนโดยการต่อท้าย.1และหากมีอยู่เช่นกัน.2และอื่น ๆ จากนั้นเป็นไฟล์ต้นฉบับที่คัดลอกไปยังปลายทาง

หากคุณต้องการคัดลอกไฟล์ในไดเรกทอรีย่อยใช้ซ้ำ-R:

cp -R --backup=existing --suffix=.orig ~/Music ~/Videos

ในขณะที่คำตอบอื่น ๆ แก้ปัญหาของฉันวิธีนี้ง่ายกว่าที่จะใช้ สิ่งนี้อาจมีประโยชน์ในอนาคต ขอบคุณ!

3

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

cp -vn "$1" "$2"/ || cp -vn "$1" "$2"/"${1##*/}"~"$(md5sum "$1" | cut -f1 -d' ')"

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

เนื่องจากสคริปต์ดังกล่าวถูกเรียกsaveCopyและเก็บไว้ในไดเรกทอรีการทำงานหลักการทำงานต่อไปนี้:

$ find . -name 'z*.jpg' -exec ./saveCopy {} /tmp/Extracted/ \;
./a/z1.jpg -> /tmp/Extracted/z1.jpg
./a/z2.jpg -> /tmp/Extracted/z2.jpg
./a/z3.jpg -> /tmp/Extracted/z3.jpg
/tmp/Extracted/z3.jpg not overwritten
./b/z3.jpg -> /tmp/Extracted//z3.jpg~d41d8cd98f00b204e9800998ecf8427e
./b/z4.jpg -> /tmp/Extracted/z4.jpg

โปรดทราบว่าสคริปต์นั้นใช้งานได้กับไฟล์อินพุตไฟล์เดียวเท่านั้นและหากเป้าหมายคือไดเรกทอรี! สามารถปรับปรุงได้อย่างแน่นอน ;-)


ดี +1 เหตุใดจึงเป็นข้อบกพร่องในการเขียนทับไฟล์ที่เหมือนกัน
terdon

@terdon ข้อบกพร่องเป็นจริงยิ่งกว่าที่คุณยังคงจบลงด้วย 2 สำเนาของไฟล์ที่เหมือนกันเพราะสำเนาแรกไม่ได้มีแฮชที่แนบมา มันไม่สอดคล้องกัน อย่างไรก็ตามฉันแค่อยากให้ตัวอย่างเล็ก ๆ ถ้าใครอยากใช้อะไรแบบนี้เป็นประจำเราควรคิดถึงวิธีที่ซับซ้อนกว่านี้เล็กน้อย
barbaz

คุณสามารถทำให้มันสอดคล้องกันมากขึ้นโดยไม่ต้องคัดลอกชื่อไฟล์ดั้งเดิมโดยใช้รหัสหลัง ||: cp -vn "$ 1" "$ 2" / "$ {1 ## * /}" ~ "md5sum" $ 1 "| ตัด -f1 -d '') "- ปัญหาคือส่วนขยายของไฟล์สับสนกับ md5sum
Robin Manoli
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.