ลบไดเร็กทอรีทั้งหมดออกจากภายในพาเรนต์ไดเร็กทอรียกเว้นหนึ่งไดเร็กทอรีและรายการที่สืบทอด


8

โครงสร้างไดเรกทอรี

ฉันต้องการลบไดเรกทอรี B และ D แต่ฉันต้องการเก็บ C และไฟล์และไดเรกทอรีที่สืบทอดทั้งหมด อะไรคือคำสั่งที่จะลบไดเรกทอรีลูกทั้งหมดของไดเรกทอรีแม่ยกเว้นหนึ่งไดเรกทอรีและลูก ๆ ของมัน

ช่วยชื่นชม


ไดเรกทอรีที่คุณต้องการลบที่ว่างเปล่าคืออะไร?
Elder Geek


แล้วไฟล์ที่อยู่ในไดเรกทอรีหลักโดยตรง ( Aในตัวอย่างของคุณ) ล่ะ? ลบพวกเขาเช่นกันหรือเก็บไว้?
ผู้บัญชาการไบต์

สิ่งที่ผู้บัญชาการ Byte ถามคือมีไฟล์ใดบ้างใน A? หรือเฉพาะไดเรกทอรี คุณต้องการไฟล์ปกติในไดเรกทอรีที่ถูกลบออกหรือเฉพาะ?
Sergiy Kolodyazhnyy

คำตอบ:


6

สิ่งที่คุณต้องการคือคำสั่งนี้:

find ~/TESTDIR -mindepth 1 -maxdepth 1 -type d -not \( -name "keepMe" \) -exec rm -rf {} \;

การสาธิต:

# List what's inside directory we want to remove
$ ls
file1  file2  keepMe/  removeA/  removeB/
# Testing what find gives without removing
$ find ~/TESTDIR -mindepth 1 -type d -not \( -name "keepMe" \)               
/home/xieerqi/TESTDIR/removeA
/home/xieerqi/TESTDIR/removeB
# Actual removal and testls
$ find ~/TESTDIR -mindepth 1 -maxdepth 1 -type d -not \( -name "keepMe" \) -exec rm -rf {} \;
$ ls
file1  file2  keepMe/

คำอธิบาย:

  • find DIRECTORY เรียกใช้คำสั่ง find เพื่อทำงานกับ DIRECTORY
  • -mindepth 1 : ทำงานเฉพาะกับเนื้อหาของไดเรกทอรีหลีกเลี่ยงไดเรกทอรีที่ระดับ 0
  • -maxdepth 1: ป้องกันการลดระดับลงในไดเรกทอรีย่อย ( rm -rfเรียกซ้ำได้ดังนั้นเราจึงไม่จำเป็นต้องลงไปในไดเรกทอรีย่อยเพื่อลบออก)
  • -type d : ค้นหาเฉพาะไดเรกทอรี
  • -not \( -name "keepMe" \) เพิกเฉยรายการที่มีชื่อที่คุณต้องการเก็บ
  • -exec rm -rf {} \; ดำเนินการลบรายการที่พบแต่ละรายการ

คำอธิบายที่ดี การกดแป้นหลายครั้งเกินไปสำหรับฉัน ...
Elder Geek

1
findเป็นเพื่อนที่ดีที่นี่ แต่ Bash's forและtestเป็นเพื่อนที่ดีกว่า ... >: - D
ผู้บัญชาการ Byte

8

การใช้คุณสมบัติแบบขยายของเชลล์ bash shell (ซึ่งถูกเปิดใช้งานโดยค่าเริ่มต้นในการติดตั้ง Ubuntu ปัจจุบัน)

$ tree A
A
├── B
├── C
│   ├── ac1
│   └── ac2
└── D

5 directories, 0 files

คุณสามารถระบุทุกอย่างที่ไม่รวมCและเนื้อหาโดยใช้นิพจน์ glob A/!(C)เช่น

$ echo A/!(C)
A/B A/D

ดังนั้นในการลบทุกอย่างยกเว้นไดเรกทอรีCและเนื้อหาคุณสามารถใช้

rm -rf A/!(C)

การออกจาก

$ tree A
A
└── C
    ├── ac1
    └── ac2

3 directories, 0 files

เป็นเรื่องน่าอัศจรรย์ที่รู้เกี่ยวกับคุณสมบัตินี้ มันใช้งานได้ดีหลังจากฉัน ssh และทำงานด้วยตนเอง แต่ฉันได้รับ `" -bash: บรรทัดที่ 1: ข้อผิดพลาดทางไวยากรณ์ใกล้โทเค็นที่ไม่คาดคิด('"เมื่อฉันเรียกใช้จากระยะไกลผ่านทางssh $VM_ADDRESS "rm -rf $APP_FOLDER/!(node_modules)"ความคิดใด ๆ ขอบคุณมาก
Renato Gama

@renatoargh extglobตัวเลือก shell เปิดใช้งานสำหรับเชลล์แบบโต้ตอบเท่านั้น - ไม่แน่ใจว่าคุณสามารถบังคับsshให้ทำเช่นนั้นได้หรือไม่
steeldriver

5

วิธีง่าย ๆ อย่างหนึ่งคือการใช้ถังขยะ -ci

คุณสามารถติดตั้งได้ด้วย sudo apt-get install trash-cli

เมื่อติดตั้งแล้วคุณสามารถนำทางไปยังไดเรกทอรีหลัก A ด้วยcd /Aแล้วออกคำสั่ง trash B Dที่ B และ D เป็นไดเรกทอรีที่คุณต้องการลบ (พวกเขาจะลงเอยในถังขยะสำหรับไดรฟ์ที่พวกเขาอยู่ดังนั้นถ้าคุณทำผิดคุณสามารถ กู้คืนไฟล์)

ทดสอบภายใต้ Ubuntu 16.04 และ 14.04


สิ่งนี้สามารถลดความซับซ้อนลงไปด้วยสิ่งที่ชอบtrash ! Cหรือไม่
Sergiy Kolodyazhnyy

@Serg Nope trash: cannot trash non existent ! ''
Elder Geek

@Serg และ C ถูกทิ้งในถังขยะ ...
Elder Geek

พบมัน: stackoverflow.com/q/216995/3701431 มันต้องมีการเปิดใช้งานextglobแม้ว่า
Sergiy Kolodyazhnyy

@Serg ขึ้นอยู่กับงานในมือที่อาจมีประโยชน์มาก! ;-)
ผู้สูงอายุ Geek

4

เพียงใช้การforวนซ้ำของ Bash และtestกรองไดเรกทอรีที่ต้องการและrm -rfคำสั่งเพื่อลบไดเรกทอรีซ้ำดังนี้:

for x in /path/to/parent/*; do test "$x" != "dir_survive" && rm -rf "$x"; done

iterates นี้มากกว่าองค์ประกอบทั้งหมด (ไฟล์และไดเรกทอรี) ภายในและลบองค์ประกอบซ้ำถ้าชื่อของมันคือไม่เท่ากับ/path/to/parent/ dir_surviveหากไดเรกทอรีหลักเป็นไดเรกทอรีปัจจุบันคุณอาจเขียน*เป็นเส้นทางเท่านั้น

หากคุณไม่แน่ใจและต้องการทดสอบองค์ประกอบที่จะถูกลบก่อนโดยไม่ต้องดำเนินการใด ๆ เพียงแค่แทนที่rm -rfคำสั่งในข้างต้นด้วยechoและมันจะออกเฉพาะผู้สมัครลบ

นี่คือตัวอย่างการเรียกใช้:

$ tree
.
├── dir1
│   ├── subdir1
│   │   ├── file1
│   │   └── file2
│   └── subdir2
│       ├── file1
│       └── file2
├── dir2
│   ├── subdir1
│   │   ├── file1
│   │   └── file2
│   └── subdir2
│       ├── file1
│       └── file2
└── dir_survive
    ├── subdir1
    │   ├── file1
    │   └── file2
    └── subdir2
        ├── file1
        └── file2

9 directories, 12 files

$ for x in *; do test "$x" != "dir_survive" && rm -rf "$x"; done

$ tree
.
└── dir_survive
    ├── subdir1
    │   ├── file1
    │   └── file2
    └── subdir2
        ├── file1
        └── file2

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