
Estou tendo o seguinte problema. Eu tenho uma estrutura de diretórios e quero excluir tudo que está dentro de um diretório chamado Caches
. Tudo deve ser excluído, exceto todos os diretórios nomeados Snapshots
. Não consigo descobrir como fazer isso comencontrarou qualquer outro comando que eu conheça.
Estou perguntando: no iOS, cada aplicativo tem seu próprio diretório de caches. Às vezes, eles não são limpos corretamente, dependendo do aplicativo. Com a solução para esta resposta, seria possível limpar caches no iOS e, portanto, otimizar o espaço em disco, quando a unidade dos dispositivos estiver montada em outro computador, por exemplo, com FUSE (iExplorer).
Isto é o que tenho até agora:
find . 2>/dev/null -type d -name "Caches" -maxdepth 3 -print
Isso retorna algo como:
./Library/Caches
Quando faço isso, ls ./Library/Caches
vejo todo o conteúdo e o Snapshots
diretório, que quero excluir porque, no final das contas, quero -delete
tudo, exceto este.
Eu quero algo assim:
Before: After:
. .
├── a ├── a
│ ├── a │ ├── a
│ └── Caches │ └── Caches
│ ├── a │ └── a
│ │ └── Snapshots │ └── Snapshots
│ │ └── a │ └── a
│ ├── b └── b
│ │ └── a └── c
│ └── c
└── b
├── c
└── Caches
├── a
│ └── foo
│ └── a
└── b
└── a
Responder1
Estou um pouco confuso com a formulação da pergunta. Se o que você deseja fazer é excluir tudo do ./Library/Caches
diretório, exceto uma única pasta chamada Snapshots
, não há necessidade de usar find
. Em bash
, shell globs são a maneira mais simples:
shopt -s extglob # probably already enabled
echo Library/Caches/!(Snapshots)
Se isso imprimir todos os arquivos/diretórios que você deseja excluir, substitua echo
por rm -f --
.
Se houver vários Snapshots
diretórios em diferentes níveis da árvore de diretórios abaixo ./Library/Caches
que você deseja preservar, então com o GNU find
você pode fazer:
find Library/Caches ! -path '*Snapshots*'
Isso deve imprimir todos os arquivos/diretórios, excluindo aqueles que estão Snapshots
em seu caminho. Incluirá diretórios que contêm (ou cujos filhos contêm) Snapshots
diretórios, porém find ... -delete
não os excluirá e, em vez disso, imprimirá um erro informando que eles não estão vazios. Quando estiver satisfeito, adicione -delete
ao final.
Uma ressalva é que isso deixará qualquerarquivosnomeado Snapshots
intacto. Se isso for um problema, faça:
find Library/Caches \( ! -path '*Snapshots*' -o -type f -name Snapshots \)
Adicione novamente -delete
quando estiver satisfeito.
Responder2
find . -depth -print0 | perl -0lne '
if ("$_/" =~ m{/Caches(/.*)}s && $1 !~ m{/Snapshots/}) {rmdir $_ or unlink $_}'
Se o seu find
não suportar -print0
, você pode substituí-lo por -exec printf '%s\0' {} +
.
A idéia é imprimir a lista de arquivos terminados em NUL (já que 0 é o único byte que não pode ocorrer em um caminho de arquivo) e usar a opção perl
's -n
with -0
para executar algum código para cada um desses nomes de arquivo (com $_
definido para o nome do arquivo ).
Com -depth
, os arquivos são impressos antes do diretório pai. Removemos apenas arquivos ou diretórios (supondo que estejam vazios, por isso é importante processar a lista em depth
ordem) se o caminho /Caches/
não contiver seguido por /Snapshosts/
.
Responder3
Eu não sou um find
feiticeiro, então não quero dizer que você não pode fazer isso find
, mas sei que isso pode ser feito com algumas linhas de bash
. Dado que entendi sua estrutura de diretórios corretamente:
#!/bin/bash
for i in Library/Caches/*; do
if [[ -d "$i" ]]; then
[[ "$i" =~ "Snapshots" ]] || echo "rm-ing $i" # change to rm -rf "$i" to use
fi
done
A for
instrução retorna cada item em Library/Caches/
. A if [[ -d "$i" ]]
instrução verifica se cada item é um diretório e, se for, seu nome é verificado para ver se contém "Snapshots", [[ "$i" =~ "Snapshots" ]]
. Como não há um operador para negar uma correspondência de regex, como !=~
, eu costumava ||
executar rm
se o comando anterior não tivesse êxito, por exemplo, o nome do diretório não contém instantâneos.
Isso será executado em qualquer sistema moderno usando bash
, mas deve ter bash
. Além disso, você pode precisar brincar com a estrutura de diretórios, mas isso deve bastar para você.
Responder4
Primeira parte: encontre diretórios chamados caches e faça algo com eles
find . -name Caches -type d -exec … \;
Segunda parte: percorrer um diretório de cache e remover tudo, mas manter Snapshots
os subdiretórios e seu conteúdo (bem como os caminhos que levam a eles). Faça uma travessia em profundidade, para que os diretórios possam ser excluídos quando ficarem vazios.
find /path/to/Caches -depth -name Snapshots -type d -prune \
-o \( -type d -empty -o ! -type d \) -delete
Agora combine-os.
find . -name Caches -type d -exec
find {} -depth -name Snapshots -type d -prune \
-o \( -type d -empty -o ! -type d \) -delete