Czy RM może rekurencyjnie usuwać puste katalogi?

9

W starej wersji Uniksa rmpolecenie usuwałoby katalogi, gdyby były puste. Ze strony podręcznika Research Unix Eighth Edition dla rm : „Jeśli wpis jest katalogiem, jest usuwany tylko wtedy, gdy jest pusty”. Podoba mi się to zachowanie, więc mam ten alias /etc/profile: alias rm='rm -d'używam wersji GNU coreutils rm, w której -dkaże rmiść do przodu i usuwać katalogi, jeśli są puste.

Na razie w porządku. Ten alias pozwala mi używać rmjak za dawnych czasów. Chciałbym jednak pójść o krok dalej. chciałbymrmaby usunąć katalog, nawet jeśli katalog zawiera inne katalogi, o ile katalogi są tam jedyne. Nie ma znaczenia, jak głęboka jest struktura katalogów, o ile nie ma tam żadnych plików, po prostu puste (po przejściu na dół) katalogi, chciałbym rmje wszystkie usunąć.

Czy można to zapisać jako alias, który nadal działałby jako zwykły rmi usuwał wszelkie przekazywane do niego pliki?

WhiteHotLoveTiger
źródło
Jak o rmdir -p?
Kevin
Dzięki za sugestię, Kevin, ale nie jest to zachowanie, którego szukam. Jeśli ucieknę mkdir -p a/b1/c2 && mkdir -p a/b2/c2; rmdir -p a/b1/c1;, wciąż pozostanie mi a, a / b2 i a / b2 / c2. Chciałbym przekazać tylko najwyższy poziom (w tym przypadku a) rmi usunąć wszystko poniżej.
WhiteHotLoveTiger

Odpowiedzi:

8

Chcesz przejść przez drzewo katalogów i sprawdzić, czy zawiera ono coś innego niż katalog. To jest poza rmmożliwościami. Potrzebujesz innych narzędzi, takich jak find. W ten sposób możesz usunąć puste katalogi w danym katalogu ( -depthpowoduje również usunięcie katalogów nadrzędnych, które stają się puste):

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

Oto funkcja, która dla każdego argumentu usuwa argument, jeśli jest to plik spoza katalogu lub drzewo katalogów nie zawierające niczego innego niż katalogi. Zauważ, że ta funkcja nie jest atomowa: jeśli jeden z argumentów zmieni się podczas działania, możesz skończyć z komunikatem o błędzie, ale jest bezpieczny, ponieważ nie usunie żadnego katalogu poza katalogiem przekazanym jako argument.

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
}
Gilles „SO- przestań być zły”
źródło