วิธีคัดลอกผสานสองไดเรกทอรี?


112

ฉันมีสองภาพไดเรกทอรีและ images2 กับโครงสร้างนี้ใน Linux:

/images/ad  
/images/fe  
/images/foo  

... และอีก 4,000 โฟลเดอร์

และอื่น ๆ ที่เป็นเช่น:

/images2/ad  
/images2/fe  
/images2/foo

... และอีก 4,000 โฟลเดอร์

แต่ละโฟลเดอร์เหล่านี้มีรูปภาพและชื่อไดเรกทอรีภายใต้รูปภาพและ images2 เหมือนกันทุกประการอย่างไรก็ตามเนื้อหาในโฟลเดอร์นั้นแตกต่างกัน จากนั้นฉันอยากรู้ว่าฉันสามารถคัดลอกภาพของ / images2 / ad ลงใน images / ad ได้อย่างไรรูปภาพของ / images2 / foo ลงใน images / foo และอื่น ๆ ด้วยโฟลเดอร์ทั้งหมด 4000 โฟลเดอร์ ..


1
ไฟล์สิ้นสุดมีชื่อเหมือนกันในทั้งสองไดเรกทอรีหรือไม่
Simply_Me

ไม่ ... ตัวอย่างเช่นในภาพ / โฆษณาคือ 1.jpg, 2.jpg และ 3.jpg แต่ใน images2 / ad คือ 4.jpg และ 5.jpg
ssierral

4
@AmirAliAkbari ฉันไม่คิดว่ามันจะซ้ำกัน - คำถามอื่น ๆ โดยทั่วไปคือ 'mv ทำการรวมกันหรือไม่' (คำตอบ: ไม่) คำถามนี้เกี่ยวกับวิธีผสานลำดับชั้นไดเรกทอรี 2
maxschlepzig

คำตอบ:


173

นี่คืองานสำหรับrsync การทำเชลล์ด้วยตนเองนั้นไม่มีประโยชน์หากคุณไม่ต้องการย้ายไฟล์แทนที่จะคัดลอก

rsync -a /path/to/source/ /path/to/destination

ในกรณีของคุณ:

rsync -a /images2/ /images/

(หมายเหตุต่อท้ายเครื่องหมายทับimages2มิฉะนั้นจะคัดลอกไป/images/images2)

หากภาพที่มีชื่อเดียวกันที่มีอยู่ในไดเรกทอรีทั้งสองคำสั่งข้างต้นจะเขียนทับด้วย/images/SOMEPATH/SOMEFILE หากคุณต้องการที่จะเปลี่ยนเฉพาะไฟล์เก่าเพิ่มตัวเลือก/images2/SOMEPATH/SOMEFILE -uหากคุณต้องการเสมอรุ่นในเพิ่มตัวเลือก/images--ignore-existing

หากคุณต้องการย้ายไฟล์/images2ด้วย rsync คุณสามารถผ่านตัวเลือก--remove-source-filesได้ จากนั้น rsync จะคัดลอกไฟล์ทั้งหมดตามลำดับและลบแต่ละไฟล์เมื่อเสร็จสิ้น สิ่งนี้ช้ากว่าการย้ายหากไดเรกทอรีต้นทางและปลายทางอยู่ในระบบไฟล์เดียวกัน


14
.. เพิ่ม -P หากคุณต้องการดูความคืบหน้า ..
Meetai.com

1
ฉันจะเพิ่มว่ามีประโยชน์กับการใช้ห่วงเปลือกหากินที่นี่แม้ว่าคุณจะไม่มีไม่ต้องการที่จะย้ายพวกเขาแทนการคัดลอกในกรณีที่ว่าเพียงแค่ใช้แล้วrsync rm -r /images
Wildcard

1
ฉันยังอยากจะชี้ให้เห็นว่ามันเป็นสิ่งสำคัญที่จะรวมถึงทับต่อท้ายสำหรับแต่ละไดเรกทอรี ตัวอย่างเช่นถ้าคุณวิ่งเพียงแค่rsync -a images images2มันจะคัดลอก images2 เป็นภาพแทนที่จะรวมเข้าด้วยกัน
Kyle Challis

1
@ s3cur3 โอ้ ตั้งแต่ 2 ถึง (โดยนัย) 1. ใช้งานง่าย ขอบคุณฉันคงคำตอบของฉัน
Gilles

1
@MaxCoplan ไม่ใช่ Rsync ไม่ใช่เครื่องมือโต้ตอบ
Gilles

43

ตัวเลือกที่ดีที่สุดตามที่โพสต์ไปแล้วนั้นเป็นของ rsync แน่นอน อย่างไรก็ตามความพร้อมเพรียงก็จะเป็นซอฟต์แวร์ที่ยอดเยี่ยมในการทำงานนี้ ทั้งสองสามารถใช้ในระบบปฏิบัติการหลายระบบ

rsync

rsync ประสานในทิศทางเดียวจากต้นทางไปยังปลายทาง ดังนั้นคำสั่งดังต่อไปนี้

rsync -avh --progress Source Destination

ซิงค์ทุกอย่างจากแหล่งที่มาเพื่อปลายทาง โฟลเดอร์ที่ผสานอยู่ในปลายทาง

-หมายถึง "เก็บถาวร" และคัดลอกทุกอย่างซ้ำ ๆ จากต้นทางไปยังปลายทางรักษาเกือบทุกอย่าง

-vให้เอาต์พุตเพิ่มเติม ("verbose")

-hสำหรับมนุษย์ที่อ่านได้

- ความคืบหน้าในการแสดงจำนวนงานที่ทำ

หากคุณต้องการเพียงปรับปรุงปลายทางโฟลเดอร์กับที่ใหม่กว่าไฟล์จากโฟลเดอร์ต้นทาง:

rsync -avhu --progress source destination

ความพร้อมเพรียงกัน

พร้อมเพรียงประสานในทั้งสองทิศทาง ดังนั้นคำสั่งดังต่อไปนี้

unison Source Destination

ซิงค์ทั้งสองไดเรกทอรีในทั้งสองทิศทางและในที่สุดก็เท่ากับปลายทางปลายทาง มันเหมือนกับการทำ rsync สองครั้งจากต้นทางถึงปลายทางและในทางกลับกัน

สำหรับประเพณีขั้นสูงดูที่หน้าคู่มือหรือเว็บไซต์ต่อไปนี้:

  1. https://www.cis.upenn.edu/~bcpierce/unison/
  2. https://rsync.samba.org/

2
ฉันต้องการพูดถึงว่าเส้นทางที่ถูกต้องไปยังโฟลเดอร์ควรมีเครื่องหมายทับท้ายท้ายrsync -avh --progress source/ destination/มิฉะนั้นโฟลเดอร์ต้นทางจะถูกสร้างในโฟลเดอร์ปลายทางอย่างน้อยในกรณีของฉันที่เป็นเช่นนี้
electroid

มันใช้งานได้ดีสำหรับฉัน (ด้วยเครื่องหมายทับต่อท้ายในโฟลเดอร์) ขอขอบคุณ!
Leopoldo Sanczyk

5
for dir in images2/*; do mv "$dir"/* "images/$(basename "$dir")"; done

ห่วงมากกว่าเนื้อหาทั้งหมดของimages2การใช้ glob ขยาย (เพื่อหลีกเลี่ยงปัญหาที่มีการแยกls) แล้วเนื้อหาของรายการเหล่านั้นไปยังรายการที่ตรงกันในmv imagesใช้basenameเพื่อตัดส่วนนำimages2จากเส้นทางก้อนกลม


โปรดเพิ่มรายละเอียดเพิ่มเติมเกี่ยวกับสิ่งที่คำสั่งของคุณทำเพื่อที่จะเป็นประโยชน์สำหรับผู้อ่านในอนาคตเช่นกัน :)
Ramesh

1

@ inulinux12 คุณสามารถใช้หนึ่งบรรทัดforวนรอบต่อไปนี้จากบรรทัดคำสั่ง:

$ for dir in images2/*; do mv "$dir"/* "${dir/2/}"; done

นี่จะย้ายไฟล์ทั้งหมดจากimages2ไปยังimagesในไดเรกทอรีที่เกี่ยวข้อง หมายเหตุ: นี่ถือว่าไม่มีไฟล์ที่มีชื่อเดียวกัน

ตัวอย่างเช่น:

ก่อนดำเนินการ:

$ ls -R images*
images:
ad  adfoo  fe
images/ad:
jpg.1  jpg.2
images/adfoo:
jpg.7
images/fe:
jpg.5
images2:
ad  adfoo  fe
images2/ad:
jpg.3
images2/adfoo:
jpg.6
images2/fe:
jpg.4

หลังจากดำเนินการ:

$ ls -R images*
images:
ad  adfoo  fe
images/ad:
jpg.1  jpg.2  jpg.3
images/adfoo:
jpg.6  jpg.7
images/fe:
jpg.4  jpg.5

3
lsอย่าแยกการส่งออกของ mywiki.wooledge.org/ParsingLs
Etan Reisner

@EtanReisner ขอบคุณสำหรับคำแนะนำ; ดูเหมือนว่าสถานการณ์จะค่อนข้างแคบ แต่ได้รับข้อมูลที่ได้จากคำถาม
Simply_Me

2
@Simply_Me แม้ว่าโดยทั่วไปแล้วจะเป็นเรื่องปกติ แต่คุณไม่ต้องการให้มันระเบิดเมื่อคุณพบเคสที่คุณไม่ได้คาดหวัง มันสามารถทำให้เกิดปัญหาที่ไม่ดีจริงๆ ไม่ต้องพูดถึงว่ามันค่อนข้างบ่อย (เช่นในกรณีนี้) เกือบจะเปลี่ยนได้เล็กน้อยด้วย glob ง่ายๆ ดูคำตอบของฉันเป็นตัวอย่างของสิ่งนั้น
Etan Reisner

@Simply_Me สถานการณ์รวมถึงชื่อไฟล์ที่มีช่องว่างซึ่งค่อนข้างธรรมดาสำหรับภาพ
Gilles

@Gilles และ @Etan Reisner ขอบคุณสำหรับการป้อนข้อมูลฉันขอขอบคุณ! อัปเดตและทดสอบคำตอบของฉันเพื่อใช้การแทนที่สตริงและมาเร็วกว่าการใช้basenameในสถานการณ์เฉพาะนี้ (ไม่จำเป็นต้องโทรbasenameหา) ขอบคุณอีกครั้งสำหรับความคิดเห็นที่สร้างสรรค์
Simply_Me
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.