Exclui todas as pastas que não contêm nome de arquivo correspondente glob / regex

1

Eu quero fazer o seguinte. Eu tenho hierarquia de arquivos de profundidade 2 assim:

A
| B
| | g
| | h50000
| C

Onde A, B, C são pastas. Eu quero apagar todas as pastas sem arquivos que correspondam a padrões específicos, (no meu caso 50000 é padrão, estilo glob) no nível de profundidade 2. (Neste exemplo, a pasta C deve ser excluída apenas ao lado do conteúdo, enquanto A permanece)

No meu aplicativo, estou bem se eu excluir todas as pastas em que nenhum dos filhos contiver o nome de arquivo correspondente a um padrão. (Seria mais fácil não excluir A sem especificar em qual profundidade estou excluindo).

Como eu seria capaz de fazer isso no bash na máquina Linux?

    
por lpp 01.03.2017 / 19:23

1 resposta

1

Com find , você pode excluir um padrão:

find \! -name '*50000*' -delete

Escapar ! é necessário devido ao uso em shells.

Os diretórios com conteúdo não serão excluídos.

AVISO: uma vez que a partir da sua pergunta é um pouco claro para mim - isso excluirá outros arquivos em pastas que tenham um padrão 50000 , por exemplo, A/B/g será removido e somente arquivos (e dirs) com o nome 50000 (incluindo seus diretórios pai) serão mantidos!

Para excluir todos os diretórios que não contêm nenhum arquivo 50000 e manter diretórios com esses arquivos, juntamente com os outros conteúdos desse diretório, sugiro um método de duas etapas:

  1. listar todos os arquivos e diretórios e salvá-los em um arquivo de texto

    find . -depth -mindepth 1 > all
    
  2. lista os diretórios que precisam ser mantidos (localize somente o diretório de arquivos e impressão)

    find . -depth -name '*50000*' printf '%h\n' > keep
    
  3. escolha os arquivos e diretórios deletáveis com um grep invertido

    grep -vf keep all > deletable
    
  4. use essa lista para exclusão (apenas uma amostra)

    while read line 
    do
    
       find . -wholename "$line" -delete
    
    done < deletable
    

Observe que o ponto 4 é lento devido à natureza de ser um script de shell de linha por linha. Não é o melhor, mas fará o trabalho.

Como alternativa (e mais simples): Se você tiver acesso raiz intermediária, altere o i -atribute, impedindo alterações, incluindo exclusão, exclua tudo (pois a exclusão não é permitida para i -flagged files e dirs) e remova o sinal i no final.

#%h goes for parent directories of our hits
find -name '*5000*' -printf '%h
find \! -name '*50000*' -delete
' | xargs -0 chattr -R +i '{}' #be careful now .... rm -r * chattr -i -R *
    
por 02.03.2017 / 09:57