Considerando as respostas para esta pergunta sobre excluir pastas por nome e esta pergunta sobre parar pesquisas no primeiro positivo em uma árvore de caminho, como posso excluir todo o conteúdo de um diretório, incluindo subdiretórios e arquivos, deixando o diretório intacto e parando na primeira partida na árvore de caminhos?
Em outras palavras, eu poderia ter:
./path/to/foo/again/foo
Com a pasta ./path/to/foo contendo um arquivo bar.txt, e eu estaria procurando obter:
./path/to/foo
Não contendo arquivos ou diretórios.
Observe que o segundo link ("sobre parar pesquisas no primeiro positivo em uma árvore de caminho") não é realmente relevante porque uma solução que o ignora pode esvaziar
./path/to/foo/again/foo
e depois esvaziar./path/to/foo
; ou pode esvaziar./path/to/foo
primeiro e não chegar./path/to/foo/again/foo
(porque esse caminho não existe agora). Em qualquer caso, o objetivo será alcançado.Qualquer coisa abaixo de (algumas)
foo
correspondências-path '*/foo/*'
, mas o./path/to/foo
próprio não corresponde.find
não adiciona barras finais aos caminhos que cria e examina. Uma exceção seria algo comofind /path/to/foo/ …
where/path/to/foo/
será processado com uma barra final e corresponderá-path '*/foo/*'
. Você pode considerar-path '*/foo/?*'
, mas se você começar com/path/to/foo//
( que é um nome de caminho válido ), ele corresponderá.Então talvez
-path
e-name
?Ele lhe dará uma boa lista de nomes de caminho para excluir? A nota
./path/to/foo/again/foo
não estará nele. A lista conterá./path/to/foo/again
, portanto, se você excluiragain
corretamente,./path/to/foo/again/foo
será excluído de qualquer maneira. Nada mal, até você perceber que não haverá entrada na lista que permita excluir./path/to/foo/foo/foo
(se esse caminho existir).Outro problema
-path '*/foo/*'
é quando você fornece um ponto de partida na forma de/a/foo/starting/point
. Nesse caso, cada caminho considerado porfind
corresponderá. Com efeito, você pode inadvertidamente remover o todopoint
, enquanto sua intenção era esvaziar/a/foo/starting/point/whatever/foo/
.Se você puder
cd
até o ponto de partida, isso deve ser seguro:(
?
provavelmente não é necessário porque a especificação declara explicitamente que não deve haver uma barra final na parte do nome do caminho em relação ao que fornecemos como o caminho inicial; mas não sei se todas as implementações defind
um selvagem obedecem estritamente; então?
é apenas no caso).Mesmo que
foo
apareça no caminho para ostarting/point
, isso não importa. Emfind
quais-path
testes o nome do caminho é construído pela ferramenta, não o nome do caminho absoluto real. Quando o find começa a partir de.
então, todos os nomes de caminho que ele cria começarão.
e-path
os testarão como strings.Nota
-delete
não é portátil . Uma solução portátil pode ser uma destas:O primeiro funciona como
-delete
(o que implica-depth
): ele processa um diretório somente após todo o seu conteúdo ter sido processado.rm
obterá os nomes de caminho um por um na ordem correta e não precisará realmente trabalhar recursivamente porque qualquer diretório que tentar remover já deve estar vazio (ainda-r
é necessário para que ele possa remover diretórios). Vários nomes de caminho serão fornecidos a um únicorm
graças a+
, ainda assim provavelmente haverá mais de umrm
porque você não pode executarrm
com muitos argumentos arbitrários .find -exec … +
sabe disso e pode executar quantos comandos (rm
processos no nosso caso) precisar processar arbitrariamente muitas entradas e não atingir o limite (para comparação:xargs
também sabe disso).Em muitos casos, a solução portátil mais ideal seria executar um ou poucos
rm -r
processos que removem não-diretórios e diretórios diretamente em./path/to/foo/
, portantofind
, nem precisa ir mais fundo. Isso é o que o segundo comando faz. Observe que existe;
(escapado do shell) em vez de+
. Não queremos+
porque pode acontecerfind
decidir que o conteúdo de./path/to/foo/
não é suficiente para rodarrm
com muitos argumentos ainda, vai mais fundo para adicionar mais argumentos, encontra o conteúdo de./path/to/foo/again/foo/
, só então iniciarm
. Entãorm -r
obtém./path/to/foo/again
e (possivelmente entre outros)./path/to/foo/again/foo/whatever
, remove o primeiro (recursivamente), então reclama que o último não existe. Portanto, quando sem-depth
, é melhor executar umrm
por nome de caminho, então-exec … \;
.Mas, mesmo assim, os arquivos que não estão mais lá provavelmente acionarão avisos; não de
rm
mas defind
. É porquefind
aprende sobre o conteúdo de um diretório antes de processar o diretório. Ele faz isso mesmo se for processar o diretório primeiro (ou seja, mesmo se não houver-depth
). Após arm
remoção./path/to/foo/again
find
ainda tentará processar./path/to/foo/again/whatever
. Qualquer solução com (explícito ou implícito)-depth
está livre deste problema.Use o primeiro formulário portátil, aquele com
-depth
; ou melhor o formulário com-delete
, se apenas seusfind
suportes-delete
.Nota lateral: se você deseja esvaziar um diretório específico
cd
, acesse -o e:Com implementações comuns de
find
você nem precisa! -name .
porque elas não excluem.
e é por design . O comando simplifica para: