จะบังคับให้ 'cp' เขียนทับไดเร็กทอรีแทนที่จะสร้างอันใหม่ภายในได้อย่างไร


110

ฉันกำลังพยายามเขียนสคริปต์ Bash ที่จะเขียนทับไดเร็กทอรีที่มีอยู่ ฉันมีไดเร็กทอรีfoo/และฉันกำลังพยายามเขียนทับbar/ด้วย แต่เมื่อฉันทำสิ่งนี้:

cp -Rf foo/ bar/

สร้างbar/foo/ไดเร็กทอรีใหม่ ฉันไม่ต้องการสิ่งนั้น มีสองไฟล์ในfoo/; aและb. มีไฟล์ที่มีชื่อเดียวกันอยู่bar/ด้วย ฉันต้องการfoo/aและfoo/bแทนที่bar/aและbar/b.

คำตอบ:


124

คุณสามารถทำได้โดยใช้-Tตัวเลือกในcp. ดูหน้าชาย
cp

-T, --no-target-directory
    treat DEST as a normal file

ตามตัวอย่างของคุณโครงสร้างไฟล์ต่อไปนี้

$ tree test
test
|-- bar
|   |-- a
|   `-- b
`-- foo
    |-- a
    `-- b
2 directories, 4 files

คุณสามารถเห็นความแตกต่างที่ชัดเจนเมื่อคุณใช้-vสำหรับ Verbose
เมื่อคุณใช้เพียงแค่-Rตัวเลือก

$ cp -Rv foo/ bar/
`foo/' -> `bar/foo'
`foo/b' -> `bar/foo/b'
`foo/a' -> `bar/foo/a'
 $ tree
 |-- bar
 |   |-- a
 |   |-- b
 |   `-- foo
 |       |-- a
 |       `-- b
 `-- foo
     |-- a
     `-- b
3 directories, 6 files

เมื่อคุณใช้ตัวเลือก-Tมันเขียนทับเนื้อหารักษาปลายทางเหมือนไฟล์ปกติและไม่ไดเรกทอรี

$ cp -TRv foo/ bar/
`foo/b' -> `bar/b'
`foo/a' -> `bar/a'

$ tree
|-- bar
|   |-- a
|   `-- b
`-- foo
    |-- a
    `-- b
2 directories, 4 files

วิธีนี้จะช่วยแก้ปัญหาของคุณได้


22
ในกรณีที่มีใครสะดุดสิ่งนี้จะใช้ไม่ได้กับ OSX cp developer.apple.com/library/mac/documentation/Darwin/Reference/…
dnfehren

9
ไม่ชัดเจนว่าคำตอบนี้คือสิ่งที่ OP กำลังมองหาแม้ว่าตัวอย่างที่ให้ไว้ข้างต้นจะปิดบังปัญหา ... ด้วยตัวเลือก -T ไฟล์ที่อยู่ในเป้าหมายที่มีอยู่ ( bar/) แต่ไม่อยู่ในแหล่งที่มา ( foo/) จะถูกทิ้งไว้ ดังนั้นนี่ไม่ใช่สิ่งที่คนส่วนใหญ่คิดว่าเป็นการเขียนทับไดเร็กทอรีโดยสมบูรณ์ กล่าวคือ. หากbar/bazมีอยู่แล้วก็จะยังคงมีอยู่ในภายหลัง ...
robo

1
คำตอบนี้ตอบคำถาม op แต่ไม่ได้ระบุถึงกรณีที่มีปลายทางอยู่แล้วและคุณต้องการลบเนื้อหาที่มี แต่ไดเรกทอรีต้นทางไม่มี นี่ไม่ใช่ลักษณะการทำงานที่คาดไว้ของการคัดลอกไฟล์จากที่หนึ่งไปยังอีกที่หนึ่ง มันจะเขียนทับเฉพาะในสิ่งที่เป็นเป้าหมายซึ่งอยู่ในแหล่งที่มาเท่านั้นโดยจะไม่แตะต้องอะไรเลยในเป้าหมายที่ไม่ได้อยู่ในแหล่งที่มา คุณสามารถล้างโฟลเดอร์เป้าหมายได้โดยป้อนคำสั่งrm -rf bar/* && cp -TRv foo/ bar/
ล่วงหน้า

2
ฉันไม่ใช่คนอ่านใจ ... ฉันไม่เห็นความชัดเจนเพิ่มเติมว่า OP กำลังมองหาอะไร แต่นี่เป็นคำตอบที่แน่นอนที่ฉัน (MEEEE) กำลังมองหา
Assimilater

2
ในกรณีที่มีคนสะดุดเพราะเหตุใดลิงก์ในความคิดเห็นที่มีการโหวตมากที่สุดจึงไม่ทำงานโปรดดูที่web.archive.org/web/20170909193852/https://developer.apple.com/…
ซัลเฟอร์

48

ทำในสองขั้นตอน

rm -r bar/
cp -r foo/ bar/

11
นี้เป็นจริงเพียงตัวอย่างที่ได้รับเพื่อให้ห่างไกลที่จะให้แน่ใจว่าbarเป็นเหมือนกันในเนื้อหาที่จะfooไม่รวมกันของรายการจากfooบวกรายการอื่น ๆ barที่อาจมีอยู่แล้วใน คำตอบที่ได้รับการโหวตสูงจาก @Saurabh Meshram ด้านล่างมีปัญหานี้
robo

1
โปรดใช้ความระมัดระวังเป็นพิเศษเนื่องจากจะลบไฟล์ทั้งหมดออกจากแถบแม้กระทั่งไฟล์ที่ซ่อนอยู่
Elia Grady

mac osx: rm -rf bar/; cp -r foo/ !$
Michael Dimmitt

1
สิ่งนี้ไม่สามารถใช้งานได้เสมอไป ... หรือต้องการ ... ลองนึกดูว่าถ้าfooและbarเป็นไดเร็กทอรีขนาดใหญ่ ... อาจมีไฟล์barที่ไม่ได้อยู่ในfooที่คุณไม่ต้องการลบ นี่ไม่ควรถือเป็นคำตอบที่เป็นจริง imho
Assimilater

แม้ว่าจะใช้งานได้สำหรับฉัน แต่ไม่ใช่ทางออกที่ดีที่สุดเนื่องจากอาจมีไฟล์รวมอยู่ใน foo / แต่ไม่อยู่ในแถบ / ซึ่งจะถูกลบหลังจากทำสิ่งนี้
นิติวิทย์

48

หากคุณต้องการให้แน่ใจว่าbar/ลงท้ายเหมือนกันให้foo/ใช้rsyncแทน:

rsync -a --delete foo/ bar/

หากมีการเปลี่ยนแปลงเพียงเล็กน้อยสิ่งนี้จะดำเนินการได้เร็วกว่าการลบและคัดลอกไดเรกทอรีทั้งหมด

  • -aคือ 'โหมดเก็บถาวร' ซึ่งคัดลอกไฟล์foo/ไปยังไฟล์bar/
  • --deleteลบไฟล์พิเศษที่ไม่ได้อยู่ในfoo/ออกbar/เช่นกันเพื่อให้แน่ใจว่าbar/ท้ายที่สุดเหมือนกัน
  • หากคุณต้องการดูว่ามันทำอะไรให้เพิ่ม-vhสำหรับ verbose และมนุษย์อ่านได้
  • หมายเหตุ: fooจำเป็นต้องใช้เครื่องหมายทับหลังมิฉะนั้นrsyncจะคัดลอกfoo/ไปbar/foo/แทนที่จะเขียนทับbar/ตัวเอง
    • (Slashes หลังจากไดเรกทอรีใน rsync มีความสับสนถ้าคุณสนใจที่นี่ตักพวกเขาบอก rsync เพื่ออ้างถึง. เนื้อหาของไดเรกทอรีมากกว่าไดเรกทอรีตัวเองดังนั้นการเขียนทับจาก. เนื้อหาของการfoo/เข้าสู่เนื้อหาของbar/เรา ใช้เครื่องหมายทับทั้งสองอย่างมันสับสนเพราะมันไม่ได้ผลตามที่คาดไว้หากไม่มีเครื่องหมายทับบนทั้งสองอย่าง rsync มักจะตีความเส้นทางปลายทางอย่างลับๆราวกับว่ามีเครื่องหมายทับแม้ว่าจะเป็นการให้เกียรติกับการไม่มีเครื่องหมายทับบนต้นทาง เส้นทางดังนั้นเราจึงต้องใช้เครื่องหมายทับบนเส้นทางต้นทางเพื่อให้ตรงกับเครื่องหมายทับที่เพิ่มโดยอัตโนมัติบนเส้นทางปลายทางหากเราต้องการคัดลอกเนื้อหาของfoo/เข้าbar/มากกว่าไดเรกทอรีfoo/เชื่อมโยงไปถึงbar/เป็นbar/foo)

rsync มีประสิทธิภาพและมีประโยชน์มากหากคุณอยากรู้อยากเห็นว่ามันทำอะไรได้อีกบ้าง (เช่นการคัดลอกผ่าน ssh)


1
ชอบคำตอบนี้ดีกว่าcp -Tตัวเลือกเพราะใช้ได้กับ macosx ด้วย👍
tongueroo

18

ใช้cpคำสั่งนี้:

cp -Rf foo/* bar/

9
สิ่งนี้ไม่ได้ลบไฟล์ที่มีอยู่ใน bar แต่ไม่ได้อยู่ใน foo
Ara

5
ไม่รู้ว่าคุณหมายถึงอะไร เหตุใดcpคำสั่งจึงควรลบไฟล์จากซอร์ส
anubhava

ความเข้าใจของฉันคือเมื่อคุณ 'เขียนทับไดเรกทอรีที่มีอยู่' ด้วยอีกรายการหนึ่งในตอนท้ายไดเรกทอรีที่เขียนทับควรเป็นสำเนาของอีกรายการหนึ่ง กล่าวคือที่แถบท้ายควรเป็นสำเนาของ foo เนื่องจากเป็นกรณีของคำตอบ @ jonathan-wheeler แต่ถ้าคุณมีแถบไฟล์ / c และไม่มี foo / c แถบ / c จะไม่ถูกลบ ในบันทึกด้านข้างฉันเพิ่งสังเกตว่ามันไม่ใช่กรณีของคำตอบของ Saurabh Meshram เช่นกัน
Ara

บางทีเราอาจไม่เห็นด้วยกับความหมายของการเขียนทับสำหรับฉันโดยพื้นฐานแล้วมันแทนที่ในขณะที่คุณอาจหมายถึง megre? ยากที่จะบอกว่า OP ต้องการอะไรเพราะเธอพูดถึงไฟล์ 2 ไฟล์เท่านั้นที่มีทั้งใน foo และ bar
Ara

ไวยากรณ์นี้ยังละเว้นไฟล์จุดที่ซ่อนอยู่ จำนวนมากยังสามารถระเบิดลูกโลกได้
xpusostomos

13

คำสั่งต่อไปนี้ช่วยให้แน่ใจว่า dotfiles (ไฟล์ที่ซ่อนอยู่) รวมอยู่ในสำเนา:

$ cp -Rf foo/. bar

1
นี่คือเรื่องจริง? ดูไม่ธรรมดา.
Mateng

2
@ มะเตงฉันเพิ่งทดสอบ - ใช่มันเป็นความจริง
Matmarbon

1
.หมายถึงไฟล์ทั้งหมดในไดเร็กทอรี ดังนั้นโดยธรรมชาติแล้วไฟล์ที่ซ่อนอยู่จะรวมอยู่ด้วย
Jaspreet Singh

สวยเนี๊ยบจริงๆ คุณยังสามารถทำ "cp -RTf foo bar" บน Linux ได้อีกด้วย
xpusostomos

6

คล้ายกับ @Jonathan Wheeler มาก:

หากคุณไม่ต้องการจำ แต่ไม่ได้เขียนใหม่bar:

rm -r bar/
cp -r foo/ !$

!$ แสดงอาร์กิวเมนต์สุดท้ายของคำสั่งก่อนหน้าของคุณ


5
เคล็ดลับเกี่ยวกับ! $ สุดยอดมาก!
Lucas Morgan


-1

การดำเนินการที่คุณกำหนดไว้คือ "ผสาน" cpและคุณไม่สามารถทำเช่นนั้นด้วย อย่างไรก็ตามหากคุณไม่ได้มองหาการรวมและตกลงที่จะสูญเสียโฟลเดอร์barคุณสามารถrm -rf barลบโฟลเดอร์แล้วmv foo barเปลี่ยนชื่อได้ การดำเนินการนี้จะไม่ใช้เวลาใด ๆ เนื่องจากการดำเนินการทั้งสองอย่างเสร็จสิ้นโดยตัวชี้ไฟล์ไม่ใช่เนื้อหาของไฟล์


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