Fiz muita limpeza removendo arquivos em uma árvore de diretórios. Agora, gostaria de excluir os diretórios vazios, pois agora há muitos diretórios 'quase vazios': eles contêm apenas um .directory
arquivo oculto. Então, fazer find -empty
aparece... vazio. Não quero excluir os arquivos de ponto dos diretórios que contêm outros arquivos.
Posso pensar em algum script bash complexo encadeado find
, mas não consigo pensar em uma maneira simples de fazê-lo... Por exemplo, a solução aqui ( Linux: excluir todos os diretórios com apenas um arquivo e nenhum subdiretório ) não encontra arquivos dot.
Esclarecimento : A .directory
é um arquivo de texto oculto criado pelo KDE ( dolphin
?) e contém informações sobre como exibir o conteúdo do diretório, por exemplo, miniaturas, ou lista de arquivos, ou apenas seus ícones, etc. Quando os arquivos são excluídos, o .directory
arquivo permanece, mas agora é praticamente inútil.
Você mencionou
find -empty
, então seufind
provavelmente é GNUfind
. Nesta resposta, usarei vários recursos não portáteis do GNUfind
.Por favor, teste minha solução em um diretório expensable primeiro. A solução é:
Funciona assim:
Porque
-delete
implica-depth
, o comando processará um diretório somente após processar tudo nele. Isso é bom, pois queremos que ele processe e possivelmente exclua subdiretórios mais profundos primeiro, então quando ele chegar a um pai, há uma chance de que ele tenha ficado vazio ou quase vazio.O comando atua em arquivos do tipo diretório (
-type d
).Se o diretório atualmente considerado estiver vazio, o comando tenta excluí-lo (
-empty -delete
).Caso contrário (ou seja, se o diretório não estiver vazio), um trecho de código shell é executado. Francamente, ele será executado também se o diretório estiver vazio e a exclusão falhar; mas, neste caso, o trecho deve ser inofensivo, então está tudo bem.
O código shell usa
&&
, então cada próximo passo é executado se e somente se seu passo precedente for bem-sucedido. Os passos são:test -f …
).-mindepth 1 -maxdepth 1
) com nomes diferentes do nome "especial". Se a saída do innerfind
estiver vazia, entãogrep -q .
sairá com status de saída diferente de zero, então! grep …
nos dará um sucesso…rm
será executado para remover o arquivo "especial".Somente se isso
rm
for bem-sucedido, o-exec
teste será considerado verdadeiro para o diretório e o último-delete
será tentado.-print
imprimirá os nomes dos caminhos dos diretórios para os quais-delete
(o primeiro ou o segundo) foram bem-sucedidos.Notas:
-delete
não apagou.
nem quando estava vazio, embora tenha conseguido formalmente.-name
pega um padrão. Em geral, se o nome "especial" contiver*
,?
ou[
então você precisa ajustar o código..directory
é seguro nesse assunto.Dada a complexidade de algumas das respostas, eu diria que Perl ou Python são as ferramentas certas para percorrer uma árvore de diretórios, obter uma lista de entradas de diretório e verificar se ela é exatamente igual a uma lista de 1 elemento contendo
.directory
(e se é um arquivo regular).Ter
find
um comando complexo fork/execsh -c
para cada subdiretório parece um desperdício, e meus olhos estão vidrados tentando seguir a lógica na resposta de Kamil. Supondo que uma listagem de diretório recursiva de toda a árvore caberá facilmente na RAM do seu sistema, ferramentas simples são o caminho a seguir.Perl tem
File::Find
que recursivamente depth-first, o que é bom, mas ele quer chamar sua função de retorno de chamada em cada entrada de diretório. Então, se você quisesse uma listagem de diretório, você teria que fazer isso sozinho em cima disso. Não é um showstopper, mas não é o ideal, então eu olhei para Python.A função de biblioteca padrão do Python directory walk é
os.walk
, que é a respiração primeiro. Mas, curiosamente, ela produz um iterador deroot, dirs, files
( exemplo de uso que copiei ), onde os dois últimos são listas do conteúdo do diretórioroot
, divididos em arquivos de diretório e não diretório. É exatamente isso que queremos; ou seria em uma busca em profundidade primeiro.Para seu caso de uso, provavelmente não há problema em remover o
.directory
arquivo em um diretório contendo apenas outros diretórios? Se sim, podemos fazer isso com Python, então usefind -depth -type d -empty -delete
(ou-print -delete
para ver quais diretórios mataremos).Configuração de teste:
uso, versão de depuração-impressão:
Uso, para valer: execute o script Python para remover
.directory
arquivos, depoisfind ... -delete
para remover diretórios vazios depth-first. Eu poderia ter tido Python execfind
depois do loop se quisesse construir uma solução mais reutilizável.Tudo o que resta é
foo/a.txt
efoo/.directory
(e o diretóriofoo
em si, é claro).Limitação:
foo/bar/.directory
teria sido removido mesmo sefoo/bar/baz
não estivesse vazio e não acabou sendo removido. Não vejo uma solução trivial para isso sem fazer minha própria busca em profundidade em Python, ou voltar para Perl e usar itsFile::Find
e fazer uma listagem de diretórios eu mesmo.Eu só sei um pouco de Python, mas mesmo assim foi muito fácil fazer isso, e estou contando com bibliotecas padrão para o trabalho pesado, então espero que seja robusto.
Não tenho certeza se entendi completamente o que você está dizendo, mas isso faz o que você está perguntando?
Então execute:
O que então produzirá: