Excluindo determinados arquivos e diretórios ao excluir arquivos

11

Meu diretório de nível superior é data. datainclui vários diretórios e esses diretórios têm subdiretórios. Eu preciso remover todos os arquivos e diretórios dentro, data/exceto vários arquivos em alguns diretórios.

Por exemplo, os dados incluem os diretórios 100e 101. Eu só quero manter a.txte b.txtarquivos 100/e c.txte d.txtarquivos 101/ao remover todos os outros arquivos e diretórios em 100e 101.

Exemplo:

.
├── 100
   ├── a.txt
   ├── b.txt
   ├── c.txt
   └── d.txt
└── 101
    ├── a.txt
    ├── b.txt
    ├── c.txt
    └── d.txt

Eu uso o rm -rf !(a.txt|b.txt)comando, mas não posso aplicar esse comando para cada diretório automaticamente.

azul profundo
fonte

Respostas:

12

Como você já descobriu, pode usar o extglobrecurso ativado com:

shopt -s extglob

Isso permite excluir correspondências para que você possa fazer coisas como:

rm 100/!([ab].txt) 101/!([cd].txt)

É uma boa ideia testá-lo echoprimeiro. Este exemplo irá corresponder a qualquer coisa dentro de 100/que não seja a.txtou b.txte qualquer coisa dentro de 101/que não seja c.txtou d.txt. Se as mesmas regras de 100/aplicação também se aplicam 102/, por exemplo:

10[02]/!([ab].txt) # or
{100,102}/!([ab].txt)
sobremesa
fonte
Acabei de dar um exemplo para os diretórios 100 e 101, mas, na realidade, o número de subdiretórios é quase 20. Existe uma maneira de implementar o código acima para cada diretório sem escrever cada nome de diretório na pasta principal?
deepblue
@deepblue Por favor, forneça um exemplo exato para isso na sua pergunta ( editar ), não está claro como rmdeve saber quais arquivos manter em quais diretórios, se você não quiser especificar isso.
sobremesa
7

Você poderia usar findpara isso. Você pode negar testes findcom -notou !. Isso excluirá correspondências, em vez de encontrá-las.

Você deve tomar cuidado para não excluir nenhum dos diretórios pai dos arquivos que deseja manter, especialmente o diretório atual . , portanto, leia a saída cuidadosamente antes de excluir.

Com base no seu exemplo, você pode fazer algo assim no datadiretório

find ! -path . ! -path ./100 ! -path ./101 ! -path "./100/[ab].txt" ! -path "./101/[cd].txt"

Adicione a ! -path ./path/to/dirpara qualquer caminho que você deseja evitar a exclusão. Você pode usar metacaracteres como *, mas certifique-se de citar a expressão se o fizer, por exemplo "./path*dir", para evitar expansões indesejadas.

findé recursivo por padrão. Mesmo se não encontrarmos ./100aqui, encontraremos todo o seu conteúdo, a menos que eles correspondam ao padrão [ab].txt. Se você não conseguir corresponder a todos os nomes que deseja manter, adicione outro teste:

! -path "./100/[ab].txt" ! -path ./100/foo

Isso não encontrará a.txtou b.txtou foo, mas encontrará todos os outros arquivos.

Quando tiver certeza de que vê o que deseja, você pode adicionar -deleteao final para excluir os arquivos encontrados:

find ! -path . ! -path ./100 ! -path ./101 ! -path "./100/[ab].txt" ! -path "./101/[cd].txt" -delete
Zanna
fonte