A rm pode remover recursivamente diretórios vazios?

9

Em uma versão antiga do Unix, o rmcomando excluiria diretórios se eles estivessem vazios. Na página do manual Research Unix Eighth Edition para rm : "Se uma entrada for um diretório, ela será removida apenas se estiver vazia." Eu gosto desse comportamento, então tenho esse alias no meu /etc/profile: alias rm='rm -d'estou usando a versão GNU coreutils do rm, na qual -ddiz rmpara ir em frente e remover os diretórios, se estiverem vazios.

Por enquanto, tudo bem. Esse alias permite que eu use rmcomo nos velhos tempos. No entanto, gostaria de dar um passo adiante. eu gostariarmpara excluir um diretório, mesmo que o diretório contenha outros diretórios, desde que os diretórios sejam a única coisa lá. Não importa a profundidade da estrutura de diretórios, desde que não haja arquivos, apenas diretórios vazios (quando você chegar ao fundo), eu gostaria rmde removê-los todos.

Isso poderia ser escrito como um alias que ainda funcionaria como regular rme excluiria os arquivos passados ​​para ele?

BrancoHotLoveTiger
fonte
Que tal rmdir -p?
Kevin
Obrigado pela sugestão Kevin, mas esse não é o comportamento que estou procurando. Se eu correr mkdir -p a/b1/c2 && mkdir -p a/b2/c2; rmdir -p a/b1/c1;, ainda fico com a, a / b2 e a / b2 / c2. O que eu gostaria é de passar apenas o nível superior (a neste caso) rme remover tudo abaixo dele.
WhiteHotLoveTiger

Respostas:

8

Você deseja percorrer uma árvore de diretórios e ver se ela contém algo diferente de um diretório. Isso está além rmdos recursos. Você precisa de outras ferramentas como find. Você pode excluir os diretórios vazios em um determinado diretório desta maneira (também -depthfaz com que os diretórios pai que ficam vazios sejam excluídos):

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

Aqui está uma função que, para cada argumento, exclui o argumento se for um arquivo que não seja de diretório ou uma árvore de diretórios que não contenha nada além de diretórios. Observe que essa função não é atômica: se um dos argumentos for alterado enquanto estiver em execução, você poderá receber uma mensagem de erro, mas é seguro que não exclua nenhum diretório que não seja um diretório passado como argumento.

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- parar de ser mau'
fonte