เลิกทำการกระทำคำสั่งคัดลอก (cp)


14

ฉันคัดลอกไฟล์บางไฟล์จากโฟลเดอร์ต้นทางไปยังโฟลเดอร์ปลายทางโดยใช้บรรทัดคำสั่งร้องในเทอร์มินัล

sudo cp From_SOURCE/* To_DESTINATION/

ตอนนี้ฉันต้องการยกเลิกคำสั่งนี้


ฉันไม่แน่ใจว่าฉันเข้าใจ เพียงแค่ลบสำเนา? (ไฟล์ sudo rm)
Jacob Vlijm

@JacobVlijm มันไม่ได้เลิกทำการกระทำมันเป็นคำสั่งแยกต่างหาก หากฉันไม่ได้คัดลอกดังนั้นฉันสามารถใช้คำสั่งที่แนะนำของคุณก่อนหน้านี้ และฉันต้องใช้เวลามากขึ้นในการลบคำสั่งนี้เพื่อคัดลอกไฟล์มากกว่า 1,000 ไฟล์?
αғsнιη

@KasiyA - ตัวเลือกจะค้นหาชื่อไฟล์ทั้งหมดที่ถูกเลือกFrom_SOURCE/*และลบออกจากTo_DESTINATION/; สิ่งนี้สามารถทำได้ด้วยการทุบตี - ปัญหาที่นี่อาจรวมถึงคำสั่ง cp เขียนทับอะไรก็ได้เชื่อมโยงถูกคัดลอกไฟล์ที่มีช่องว่างในชื่อ ฯลฯ - ดังนั้นมันอาจมีปัญหาและไปแปลกประหลาดเล็กน้อย ตัวเลือก 'เลิกทำ' ที่สมบูรณ์แบบอาจต้องพิจารณาสิ่งต่างๆมากมาย
วิลฟ์

คำตอบ:


13

ถ้าฉันเข้าใจดีนี่เป็นกรณีต่อไปนี้:

  • คุณคัดลอกไฟล์ (ขนาดใหญ่) ไปยังไดเรกทอรีที่มีอยู่และคุณต้องการ / ต้องการย้อนกลับการดำเนินการ
  • ไดเรกทอรีเป้าหมายมีจำนวนไฟล์อื่น ๆที่คุณต้องเก็บไว้ซึ่งทำให้ไม่สามารถลบไฟล์ทั้งหมดออกจากไดเรกทอรีได้อย่างง่ายดาย

สคริปต์ด้านล่างดูในไดเรกทอรีต้นฉบับ (ต้นฉบับ) และแสดงรายการไฟล์เหล่านั้น จากนั้นจะดูในไดเรกทอรีที่คุณคัดลอกไฟล์ไปยังและลบเฉพาะไฟล์ที่อยู่ในรายการตามที่มีอยู่ในไดเรกทอรีต้นทาง

tryองค์ประกอบจะถูกเพิ่มเพื่อป้องกันไม่ให้เกิดข้อผิดพลาดเช่นในกรณีที่คุณอาจได้ลบบางไฟล์ด้วยตนเองแล้วหรือหากไม่ได้ไฟล์ทั้งหมดจากไดเรกทอรีต้นทางถูกคัดลอกไปยังปลายทาง หากคุณต้องการสิทธิ์ sudo เพียงแค่เรียกใช้สคริปต์ด้วย "sudo" (ดูด้านล่าง)

บท

#!/usr/bin/env python

import os

source_dir = "/path/to/source" # the folder you copied the files from
target_folder = "/path/to/destination" # the folder you copied the files to

for root, dirs, files in os.walk(source_dir):
    for name in files:
        try:
            os.remove(target_folder+"/"+name)
        except FileNotFoundError:
            pass

วิธีใช้

  • วางสคริปต์ในไฟล์ที่ว่างเปล่าบันทึกเป็นreverse.py,
  • แทรกเส้นทางที่ถูกต้องสำหรับโฟลเดอร์ต้นทางและโฟลเดอร์เป้าหมาย
  • ทำให้ปฏิบัติการได้ด้วยเหตุผลด้านความสะดวก
  • เรียกใช้โดยคำสั่ง:

    [sudo] /path/to/reverse.py
    

คำเตือน

ก่อนอื่นให้ลองทดสอบไดเรกทอรีถ้าฉันเข้าใจดีว่าคุณต้องทำอะไร!


ถ้าไดเรกทอรีที่มานั้น "แบน"

ในกรณีที่ไดเรกทอรีต้นทางไม่มีไดเรกทอรีย่อยสคริปต์สามารถทำได้ง่ายกว่า:

#!/usr/bin/env python

import os

source_dir = "/path/to/source" # the folder you copied the files from
target_folder = "/path/to/destination" # the folder you copied the files to

for file in os.listdir(source_dir):
    try:
        os.remove(target_folder+"/"+file)
    except FileNotFoundError:
        pass

บันทึก

หากการดำเนินการคัดลอกเขียนทับ (แทนที่) ไฟล์ที่มีชื่อคล้ายกันในปลายทางไฟล์จะถูกลบ แต่ไฟล์ต้นฉบับ (แน่นอน) จะไม่ถูกนำกลับมาโดยสคริปต์ สมมติฐานคือไม่มีการปะทะกันของชื่อ


มันใช้งานได้ดีขอบคุณ sudo python3 reverse.pyผมใช้มันด้วย ฉันยอมรับคำตอบของคุณ
αғsнιη

ที่สมบูรณ์แบบ! ขอขอบคุณสำหรับคำถามที่ดีซึ่งอธิบายสถานการณ์ของเราอาจได้รับทั้งหมดใน :)
จาค็อบ Vlijm

หมายเหตุ: หากไฟล์ใด ๆ ในซอร์สเขียนทับไฟล์ในปลายทางเนื่องจากมีชื่อเดียวกันคุณจะไม่สามารถเลิกทำได้และสคริปต์นี้จะลบทิ้ง cpสมมติฐานที่นี่เป็นที่ที่ไม่มีการปะทะกันชื่อเมื่อคุณได้เริ่มต้น
thomasrutter

@neon_overload แก้ไขให้แก้ไขในคำตอบของฉัน
Jacob Vlijm

cp -rนี้ไม่ได้ทำงานให้กับ ผมเปลี่ยนos.removeด้วยprintและมันก็แสดงผลพวงของไฟล์ที่ไม่ได้อยู่ ฉันสมมติว่ามันไม่มีไดเรกทอรีย่อยและแสดงเฉพาะไฟล์ในตอนท้าย
Typewar

7

TL; DR:

ไฟล์ทั้งหมดที่มีอยู่ในทั้งสองsrcและdestสามารถลบออกจากdestเช่นนี้:

find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;

สำหรับคำอธิบายทีละขั้นตอนดูด้านล่าง

ทำให้ปัญหาง่ายขึ้น:

เพื่อให้เข้าใจสิ่งที่คำสั่งที่เราต้องการเลิกทำจริงเราเริ่มด้วยการทำให้มันง่ายขึ้น:

คำสั่งที่เราต้องการยกเลิกคือ

sudo cp From_SOURCE/* To_DESTINATION/

เพื่อความเข้าใจวิธีการยกเลิกsudoไม่เกี่ยวข้อง

ฉันจะใช้ชื่อไดเรกทอรีsrcสำหรับFrom_SOURCEและสำหรับdestTo_DESTINATION

ตอนนี้คำสั่งของเราคือ:

cp src/* dest/

ถ้าsrcมีแฟ้มf1, f2และf3และไดเรกทอรีd1และd2เปลือกขยายคำสั่งที่ไปที่:

cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/

โดยไม่มีตัวเลือกชอบ-r, -Rหรือ-aคำสั่งcpไม่ลอกไดเรกทอรี
นั่นหมายความว่าคำสั่งจะปล่อยพวกเขาออกไปโดยแสดงข้อผิดพลาดสำหรับแต่ละคน:

$ cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/
cp: omitting directory 'src/d1'
cp: omitting directory 'src/d2'

destซึ่งหมายความว่าเราได้คัดลอกเฉพาะไฟล์ง่ายและไม่ไดเรกทอรีไป

การตัดสินใจว่าจะลบไฟล์ใด:

อาจมีไฟล์ในชื่อเดียวกับไฟล์ในdest srcในกรณีนี้ไฟล์ถูกเขียนทับ (1) สายเกินไปสำหรับพวกเขาขอโทษ รับพวกเขากลับจากการสำรองข้อมูลล่าสุด

เกี่ยวกับไฟล์ที่มีเราต้องการลบเฉพาะไฟล์ที่ถูกคัดลอก ไฟล์เหล่านี้มีอยู่ในทั้งสองไดเรกทอรีโดยใช้ชื่อเดียวกันและมีเนื้อหาเหมือนกัน

ดังนั้นเราจึงมองหาไฟล์เหล่านี้:

อันดับแรกเราcdเข้าไปsrcเพราะจะทำให้findคำสั่งต่อไปนี้ง่ายขึ้นมากและตั้งค่าตัวแปรเป็นเส้นทางสัมบูรณ์ของปลายทาง:

$ cd src
$ destdir="$(readlink -f dest)"

จากนั้นเราจะแสดงรายการไฟล์ทั้งหมดใน src:

$ find . -maxdepth 1 -type f

และสำหรับแต่ละไฟล์ที่พบให้ใช้cmpเพื่อตรวจสอบว่ามีไฟล์ที่มีเนื้อหาเดียวกันในปลายทางหรือไม่:

$ find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -print

การลบไฟล์อย่างระมัดระวัง:

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

$ toDelete=/tmp/toDelete ; mkdir -p "$toDelete"
$ find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec echo mv -n "$destdir/{}" "$toDelete"/ \;
mv -n /path/to/dest/./f1 /tmp/toDelete/`
mv -n /path/to/dest/./f2 /tmp/toDelete/`
mv -n /path/to/dest/./f3 /tmp/toDelete/`

ดูดี! ตอนนี้เราสามารถออกจากการechoรันmvคำสั่งจริง:

find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;

ไฟล์ทั้งหมดจากdestที่ถูกคัดลอกมาsrcและยังคงเหมือนเดิมในsrcและdestในตอนนี้/tmp/toDelete/และสามารถลบออกได้หลังจากดูครั้งสุดท้าย


หมายเหตุ:
(1) ตรวจสอบว่าcpเป็นนามแฝงcp -iหรือไม่นั้นจะป้องกันการเขียนทับไฟล์โดยถามก่อน


5

นี่เป็นรุ่นเก่า แต่ฉันแค่ต้องการโพสต์คำตอบทุบตีบริสุทธิ์:

ก่อนอื่นให้เปลี่ยนไดเรกทอรีที่คุณคัดลอกไฟล์

cd dest

จากนั้นlsไดเรกทอรีต้นทางและไพพ์เอาท์พุทลงไปrm

ls source | xargs rm


1
การแยกวิเคราะห์lsเป็นความคิดที่ไม่ดี mywiki.wooledge.org/ParsingLs ฉันจะไม่ลงคะแนนโพสต์ของคุณ แต่จะต้องมีการบันทึกไว้
Sergiy Kolodyazhnyy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.