ลบแผนผังไดเรกทอรีว่าง (ลบไดเรกทอรีมากที่สุดเท่าที่จะทำได้ แต่ไม่มีไฟล์)


13

สมมติว่าฉันมีต้นไม้ dir เช่นนี้:

ROOTDIR
    └--SUBDIR1
        └----SUBDIR2
            └----SUBDIR3

ฉันกำลังมองหาคำสั่งเช่นนั้นเมื่อฉันป้อน:

$ [unknown command] ROOTDIR

ต้นไม้ dir ทั้งสามารถลบได้ถ้าไม่มีแฟ้ม แต่ dirs ภายในต้นไม้ทั้ง อย่างไรก็ตามถ้ามีไฟล์ชื่อ hello.pdf ใต้ SUBDIR1:

ROOTDIR
    └--SUBDIR1
        └--hello.pdf
        └----SUBDIR2
            └----SUBDIR3

จากนั้นคำสั่งจะต้องลบ SUBDIR2 และด้านล่างเท่านั้น


นี่น่าจะเป็นสิ่งที่ซ้ำกันของวิธีการลบไดเรกทอรีว่างทั้งหมดในทรีย่อย?
David Cary

คำตอบ:


11

อเล็กซิสอยู่ใกล้ สิ่งที่คุณต้องทำคือ:

find . -type d -depth -empty -exec rmdir "{}" \;

ที่จะเจาะลึกไดเรกทอรีต้นไม้ก่อนจนกว่าจะพบไดเรกทอรีว่างแรกแล้วลบ ดังนั้นการทำให้ไดเรกทอรีหลักว่างเปล่าซึ่งจะถูกลบ ฯลฯ ซึ่งจะสร้างเอฟเฟกต์ที่ต้องการ (ฉันทำอย่างนี้น่าจะ 10 ครั้งต่อสัปดาห์ดังนั้นฉันค่อนข้างแน่ใจว่ามันถูกต้อง) :-)


ทำไม-depthตัวเลือกที่จำเป็น? find . -type d -empty -exec rmdir "{}" \;ควรจะทำงาน .... ใช่ไหม
Abhishek

4
พิจารณาถ้าคุณมีต้นไม้ foo/bar/baz(ไดเรกทอรีเท่านั้น) ถ้าคุณไม่ใช้-depthมันจะพยายามลบfooก่อนล้มเหลวและคุณจะจบลงด้วยfoo/barหลังจากทำงาน
l0b0

1
ทางเลือกที่เป็นไปได้ก็คือใช้+แทน;แบตช์ที่คุณลบไดเรกทอรี เนื่องจากคุณดำเนินการในระดับแรกเด็ก ๆ จะยังคงถูกลบออกต่อหน้าผู้ปกครอง (อาจขึ้นอยู่กับเวอร์ชันของ rmdir / bash ของคุณและพึ่งพา rmdir ไม่ได้ลบไดเรกทอรีที่ไม่ว่างเปล่า) สิ่งนี้ใช้ได้กับฉันในการทุบตี cygwin:mkdir -p a/b/c/d ; find a -depth -type d -exec rmdir {} +
idbrii

4
ผู้คนไปหาคำตอบที่กระชับยิ่งขึ้นของ go2null ด้านล่าง! ไม่สามารถเข้าใจว่าทำไม SE ให้ความสำคัญกับคำตอบที่ยอมรับมากกว่าคำตอบที่มี upvotes ส่วนใหญ่ในการแสดงคำตอบด้านล่างคำถาม OP ยอมรับคำตอบที่ดีที่สุดในขณะที่เขาเลือก แต่ต่อมาคำตอบที่ดีกว่าจะมาจากชุมชนที่ upvotes ไม่? (แน่นอนว่านี่คือบางอย่างสำหรับเมตา ... )
jamadagni

สิ่งนี้ไม่ได้ผลสำหรับฉัน มันจะลบใบไม้ที่ลึกที่สุด (SUBDIR3 ในกรณีนี้)
Joey Baruch

24
find ROOTDIR -type d -empty -delete

เหมือนกับ

find ROOTDIR -type d -depth -empty -exec rmdir "{}" \;

แต่ใช้การดำเนินการ "-delete" ในตัว

โปรดทราบว่า "-delete" หมายถึง "-depth"


ความรุ่งโรจน์สำหรับคำตอบที่รวบรัดที่สุดโดยใช้การลบในตัวของ find! ฉันกำลังเพิ่มสิ่งนี้ลงใน utilscripts ท้องถิ่นของฉัน!
jamadagni


1

ต่อไปนี้เป็นข้อกำหนดบางประการก่อนที่เราจะสามารถทำได้อย่างปลอดภัย:

  1. ลบไดเรกทอรีย่อยก่อนแล้วจึงไดเรกทอรีระดับบนคือเราต้องเรียงลำดับรายชื่อไดเรกทอรีหรือใช้ธง rmdir --parents
  2. เริ่มROOTDIRเสมอด้วย / หรือ. / เพื่อหลีกเลี่ยงความประหลาดใจกับไฟล์ที่ขึ้นต้นด้วย -
  3. ใช้รายการไดเรกทอรีที่ยกเลิก NUL เพื่อทำงานกับชื่อไดเรกทอรีที่มีช่องว่าง

นี่คือวิธีที่ฉันจะทำในเปลือก:

find ./ROOTDIR -type d | sort -r | tr '\n' '\000' | xargs -0 rmdir --ignore-fail-on-non-empty

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

find ./ROOTDIR -type d -print0 | xargs -0 rmdir --ignore-fail-on-non-empty --parents

รุ่งโรจน์สำหรับคำอธิบายรายละเอียดของคำตอบของคุณ ฉันอาจใช้วิธีเดียวกันจนกว่าฉันจะเรียนรู้เกี่ยวกับ-empty -deleteตัวเลือกfindในคำตอบของ @ go2null
Davor Cubranic

0
rmdir $(find ROOTDIR -type d | sort -r)

5
สิ่งนี้จะไม่ทำงานหากชื่อไดเรกทอรีใด ๆ มีช่องว่างหรืออักขระตัวกลม เป็นความคิดที่ดีที่จะใช้การแทนที่คำสั่งในรายการชื่อไฟล์ โดยเฉพาะอย่างยิ่งมันเป็นความคิดที่ดีด้วยfindเพราะมีวิธีการที่จะทำในการประมวลผลหมดจด:find find … -exec
Gilles 'หยุดความชั่วร้าย'

ขอบคุณ Gilles ที่ชี้ให้เห็น @lanzz มักโพสต์คำสั่งโดยไม่อธิบายว่ามันทำอะไร (และในกรณีนี้คือข้อผิดพลาด) นั้นไม่เพียงพอ โปรดเพิ่มคำตอบของคุณ
n0pe

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