Para fins de teste, criei os seguintes diretórios.
user@linux:~$ mkdir dir0{1..3}
user@linux:~$ ls -l
total 12K
drwxr-xr-x 2 user user 4.0K Mei 31 10:45 dir01
drwxr-xr-x 2 user user 4.0K Mei 31 10:45 dir02
drwxr-xr-x 2 user user 4.0K Mei 31 10:45 dir03
user@linux:~$
Então, eu removi comfind -exec
user@linux:~$ find -type d -exec rmdir {} \;
rmdir: failed to remove '.': Invalid argument
find: ‘./dir02’: No such file or directory
find: ‘./dir01’: No such file or directory
find: ‘./dir03’: No such file or directory
user@linux:~$
Os diretórios foram removidos, eu verifiquei.
user@linux:~$ ls -l
total 0
user@linux:~$
Minhas perguntas são:
1) Não entendo por que as mensagens estavam lá. Alguma ideia do porquê?
rmdir: failed to remove '.': Invalid argument
find: ‘./dir02’: No such file or directory
Não vejo esse tipo de erro comrmdir
user@linux:~$ mkdir dir0{1..3}
user@linux:~$
user@linux:~$ ls -l
total 12K
drwxr-xr-x 2 user user 4.0K Mei 31 22:58 dir01
drwxr-xr-x 2 user user 4.0K Mei 31 22:58 dir02
drwxr-xr-x 2 user user 4.0K Mei 31 22:58 dir03
user@linux:~$
user@linux:~$ rmdir *
user@linux:~$
user@linux:~$ ls -l
total 0
user@linux:~$
2) É possível remover essas mensagens?
Responder1
Você recebe os erros "Esse arquivo ou diretório não existe" find
porque find
está tentando entrar nos diretórios que acabou de remover. Por padrão, ele aplicará suas ações a todos os itens correspondentes no diretório que está visitando antes de continuar nos subdiretórios.
Adicione -depth
à invocação de find
to make find
uma pesquisa profunda em seus caminhos de pesquisa, o que por sua vez significa que se você executar rmdir
em um diretório, ele já o terá visitado e não tentará visitá-lo novamente.
A -depth
opção está implícita ao usar -delete
por esse motivo (em implementações find
disso -delete
).
find . -depth -type d -exec rmdir {} \;
-depth
é uma opção padrão para o find
utilitário.
Observe que rmdir
só funciona em diretórios vazios. Se você tiver muitos diretórios não vazios, o comando acima produziria muitas mensagens de erro.
Em vez disso, se você find
suportar, use -empty
:
find . -type d -empty -delete
Isso excluiria diretórios vazios.
Com um find
que não possui o não padrão -delete
nem -emtpy
:
find . -depth -type d -exec sh -c '
for dirpath do
set -- "$dirpath"/*
[ ! -e "$1" ] && rmdir "$dirpath"
done' sh {} +
Isso testaria se os diretórios encontrados estavam vazios e, se estivessem, seriam excluídos.
Esse é um longo trecho de código para evitar ver algumas mensagens de erro devido ao fato de os diretórios não estarem vazios, mas quaisquer mensagens de erro quesãoesperamos que sejam mais interessantes de se ver, pois provavelmente seriam erros de "permissão negada". Redirecionar os erros para /dev/null
o primeiro find
comando na parte superior teria ocultado tais erros.
Responder2
O que presumivelmente acontece é que, com a -exec ... \;
construção, find faz seu trabalho passo a passo:
- percorrer a árvore de diretórios, encontrando entradas que correspondam
-type d
e - execute
rmdir
essas entradas assim que forem encontradas.
Isso significa que, no seu exemplo, find irá olhar para dir01
, mantê-lo em mente como um diretório para entrar mais tarde, depois executá rmdir
-lo e, então, ao tentar recorrer a dir01
, falhará porque ele não existe mais.
Executar with -exec rmdir {} +
deve ajudar neste caso: uma única chamada rmdir dir01 dir02 dir03
será emitida. Isso elimina as últimas três mensagens de erro.
A mensagem de erro .
é porque, bem .
, o diretório atual é de fato um diretório, mas não um que rmdir
pode ser excluído, porque não está vazio. Use -min-depth
para parar de considerá-lo, fazendo o comando:
find -mindepth 1 -type d -exec rmdir {} +
Isto não é perfeito; diretórios aninhados ou um grande número de diretórios correspondentes ainda podem causar a impressão de mensagens de erro, mas isso deve funcionar no caso simples da pergunta.