rm สามารถลบไดเรกทอรีที่ว่างเปล่าซ้ำ ๆ ได้หรือไม่


9

ใน Unix เวอร์ชันเก่าrmคำสั่งจะลบไดเรกทอรีถ้าว่างเปล่า จากหน้าคู่มือการวิจัย Unix Eighth Edition สำหรับ rm : "ถ้ารายการเป็นไดเรกทอรีรายการนั้นจะถูกลบออกหากว่างเปล่า" ฉันชอบพฤติกรรมนี้ดังนั้นฉันจึงมีนามแฝงนี้ในของฉัน/etc/profile: alias rm='rm -d'ฉันใช้รุ่น GNU coreutils rmซึ่ง-dบอกrmให้ไปข้างหน้าและลบไดเรกทอรีหากไม่มี

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

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


แล้วไงrmdir -pล่ะ
Kevin

ขอบคุณสำหรับคำแนะนำของเควิน แต่นี่ไม่ใช่พฤติกรรมที่ฉันกำลังมองหา ถ้าฉันวิ่งmkdir -p a/b1/c2 && mkdir -p a/b2/c2; rmdir -p a/b1/c1;ฉันยังเหลือ a, a / b2 และ a / b2 / c2 สิ่งที่ฉันต้องการคือการส่งระดับสูงสุด (ในกรณีนี้) ไปยังrmและลบทุกอย่างด้านล่าง
WhiteHotLoveTiger

คำตอบ:


8

คุณต้องการสำรวจทรีไดเรกทอรีและดูว่ามีสิ่งใดนอกจากไดเรกทอรี นี่มันเกินrmความสามารถของ คุณจำเป็นต้องมีเครื่องมืออื่น ๆ findเช่น คุณสามารถลบไดเรกทอรีว่างเปล่าภายใต้ไดเรกทอรีที่กำหนดด้วยวิธีนี้ ( -depthทำให้ไดเรกทอรีหลักที่กลายเป็นว่างเปล่าที่จะถูกลบเช่นกัน):

find "$x" -depth -type d -exec rmdir {} +

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

rm () {
  ret=0
  for x; do
    case $x in -*) x=./$x;; esac
    if [ -d "$x" ]; then
      if [ -n "$(find "$x" ! -type d | head -n 1)" ]; then
        echo 1>&2 "$x: non-empty directory tree"
        ret=2
      else
        find "$x" -depth -exec rmdir {} +
        if [ -d "$x" ]; then ret=2; fi
      fi
    else
      command rm "$x" || [ $ret -gt 1 ] || ret=2
    fi
  done
  return $ret
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.