Como excluir este diretório não excluído?

40

Descompactei um arquivo tar corrompido e consegui terminar com algum diretório que não consigo excluir. Se tentar excluí-lo, parece que ele não pode ser encontrado, mas lsmostra que está presente, tanto no bash quanto no python que recebo comportamento semelhante, exceto logo depois que eu tento excluí-lo rm -rf, lsreclama que ele não pode encontrá-lo e, em seguida, lista-o (veja abaixo depois rm -rf). O findcomando mostra que o arquivo está presente, mas ainda não consigo pensar em uma maneira de excluí-lo.
Aqui estão minhas tentativas:

Aqui você vê os dois lse findconcorda que temos um diretório,

rl]$ ls
mikeaâ??cnt
rl]$ find -maxdepth 1 -type d -empty -print0  
./mikeaâcnt 

Mas não posso excluí-lo:

rl]$ find -maxdepth 1 -type d -empty -print0 |  xargs -0 rm -f -v 
rm: cannot remove `./mikeaâ\302\201\302\204cnt': Is a directory
rl]$ ls
mikeaâ??cnt

Eu posso cdfazer isso e está vazio:

rl]$ cd mikeaâ^Á^Äcnt/
mikeaâ^Á^Äcnt]$ ls
mikeaâ^Á^Äcnt]$ pwd
.../rl/mikeaâcnt


mikeaâ^Á^Äcnt]$ cd ../
rl]$ ls
mikeaâ??cnt

veja abaixo que não é um arquivo simples, mas um diretório, além de lsse comportar de maneira engraçada depois rm -rf que diz que não consegue encontrar o arquivo e o lista imediatamente:

rl]$ rm mikeaâ^Á^Äcnt/
rm: cannot remove `mikeaâ\302\201\302\204cnt/': Is a directory
rl]$ rm -rf  mikeaâ^Á^Äcnt/
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
rl]$ 

Portanto, esta é a tentativa com python, o arquivo foi encontrado, mas o nome não pode ser usado como um nome que pode ser excluído:

rl]$ python 
Python 2.6.6 (r266:84292, Jul 10 2013, 22:48:45) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> import shutil
>>> os.listdir('.')
['mikea\xc3\xa2\xc2\x81\xc2\x84cnt']
>>> shutil.rmtree(os.listdir('.')[0] )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.6/shutil.py", line 204, in rmtree
    onerror(os.listdir, path, sys.exc_info())
  File "/usr/lib64/python2.6/shutil.py", line 202, in rmtree
    names = os.listdir(path)
OSError: [Errno 2] No such file or directory: 'mikea\xc3\xa2\xc2\x81\xc2\x84cnt'

mesmo quando uso o preenchimento da guia, o nome escolhido não é utilizável:

rl]$ rm -rf mikeaâ^Á^Äcnt 
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

usando o nome que python mostra com bash, recebo o seguinte:

rl]$ rm -rf "mikea\xc3\xa2\xc2\x81\xc2\x84cnt"
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

Existe algo que eu possa fazer para me livrar desse diretório corrompido? O sistema de arquivos subjacente (NFS) parece funcional e nenhum outro problema foi relatado, e eu não tive esses problemas até o arquivo tar corrompido.

EDIT: Aqui está usando finda própria -execopção para chamarrm

rl]$ find -maxdepth 1 -type d -empty -exec rm -f {} \;
find: `./mikeaâ\302\201\302\204cnt': No such file or directory
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
rl]$

mas o arquivo ainda está lá ( lsreclama que não foi encontrado, mas mostra mesmo assim)

2ª EDIÇÃO:

rl]$ find -maxdepth 1 -type d -empty -exec rm -rf {} \;
find: `./mikeaâ\302\201\302\204cnt': No such file or directory
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

O comportamento ainda é inalterado, o arquivo ainda está presente

3ª EDIÇÃO:

rl]$ ls
mikeaâ??cnt
rl]$ find -maxdepth 1 -type d -empty -exec rm -rf {} + 
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

Parece haver mais no nome do que mikeaâcntolhar para a saída da tentativa de python mikea\xc3\xa2\xc2\x81\xc2\x84cnte esta captura de tela:

ls output

4ª EDIÇÃO: Esta é a tentativa com um curinga:

rl]$ echo * 
mikeaâcnt
rl]$ echo mike* 
mikeaâcnt
rl]$ rm -rf mike*
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

e meu local:

rl]$  locale
LANG=en_US.utf8
LC_CTYPE="en_US.utf8"
LC_NUMERIC="en_US.utf8"
LC_TIME="en_US.utf8"
LC_COLLATE="en_US.utf8"
LC_MONETARY="en_US.utf8"
LC_MESSAGES="en_US.utf8"
LC_PAPER="en_US.utf8"
LC_NAME="en_US.utf8"
LC_ADDRESS="en_US.utf8"
LC_TELEPHONE="en_US.utf8"
LC_MEASUREMENT="en_US.utf8"
LC_IDENTIFICATION="en_US.utf8"
LC_ALL=

5a Edição:

rl]$ ls -i 
ls: cannot access mikeaâcnt: No such file or directory
? mikeaâ??cnt

mas também o comportamento mudou, agora lse cd faça o seguinte:

rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
rl]$ cd mikeaâ^Á^Äcnt 
mikeaâcnt: No such file or directory.

Isso aconteceu após as tentativas de exclusão. Estou pensando que podem ser problemas de NFS, conforme sugerido em uma das respostas aqui por vinc17.

6ª EDIÇÃO: Esta é a saída lsofels -a

rl] $ / usr / sbin / lsof mikeaâ € ïcnt lsof: erro de status no mikeaâ \ xc2 \ x81 \ xc2 \ x84cnt: esse arquivo ou diretório não existe

acima está errado, aqui está a lsofchamada correta : (rl é o diretório pai)

rl]$ /usr/sbin/lsof | grep mike | grep rl 
tcsh      11926   mike  cwd       DIR   0,33     4096 19569249 /home/mike/mish/rl
lsof      14733   mike  cwd       DIR   0,33     4096 19569249 /home/mike/mish/rl
grep      14734   mike  cwd       DIR   0,33     4096 19569249 /home/mike/mish/rl
grep      14735   mike  cwd       DIR   0,33     4096 19569249 /home/mike/mish/rl
lsof      14736   mike  cwd       DIR   0,33     4096 19569249 /home/mike/mish/rl
rl]$ 

rl]$ ls -a
ls: cannot access mikeaâcnt: No such file or directory
.  ..  mikeaâ??cnt

7ª Edição: movimento não vai funcionar, (eu tentei antes de tudo isso, mas eu não salvou a saída), mas tem o mesmo problema que lse rm com o arquivo.

8ª EDIÇÃO: use os caracteres hexadecimais, conforme sugerido:

 rl]$ ls --show-control-chars | xxd
0000000: 6d69 6b65 61c3 a2c2 81c2 8463 6e74 0a    mikea......cnt.
rl]$ rmdir $'mikea\6d69\6b65\61c3\a2c2\81c2\8463\6e74\0acnt' 
rmdir: failed to remove `mikea\006d69\006b651c3\a2c2\\81c2\\8463\006e74': No such file or directory
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
rl]$

9a Edição: para o statcomando:

 rl]$ stat  mikeaâ^Á^Äcnt 
stat: cannot stat `mikeaâ\302\201\302\204cnt': No such file or directory
 rl]$

Parece ainda mais provável de toda a saída, há um bug ou outro mau comportamento do NFS, conforme sugerido nos comentários.

Edit 10: Esta é a saída strace em uma essência, pois é tão grande, é a saída ou estes dois comandos:

strace -xx rmdir ./* | grep -e '-1 E'`
strace -xx -e trace=file ls -li`

https://gist.github.com/mikeatm/e07fa600747a4285e460

Edit 11: Então, antes do exposto rmdir, notei que podia cdentrar no diretório, mas após o rmdirnão consegui cdnovamente, semelhante a ontem. Os arquivos .e ..estavam presentes:

rl]$ ls
mikeaâ??cnt
rl]$ cd mikeaâ^Á^Äcnt/
mikeaâ^Á^Äcnt]$ ls
mikeaâ^Á^Äcnt]$ ls  -a
.  ..
mikeaâ^Á^Äcnt]$ cd ../

Edição final: vi um administrador local sobre isso e foi resolvido fazendo logon no próprio servidor e excluindo a partir daí. A explicação deles é que poderia ser um problema com conjuntos de caracteres no nome sendo inapropriados.

mike-m
fonte
Existe uma razão para você canalizar finda saída para um comando diferente em vez de apenas usar sua execopção?
HalosGhost
@HalosGhost não havia nenhuma razão, ver edição para informação adicional sobre a sua pergunta
mike-m
2
Como alguém com muito pouca experiência com unix e linux, eis a minha ideia: tente renomear o diretório para algo sem usar esses símbolos mv. talvez você possa excluí-lo depois disso. Como alternativa, você pode tentar mover o diretório para um nível de pasta mais profundo (talvez com um curinga) e excluir a pasta para a qual você o moveu.
Nzall 30/07
4
Suspeito que o diretório exista apenas na memória do cliente e já esteja no servidor há muito tempo. Você já tentou desmontá-lo e montá-lo novamente? Você já tentou reiniciar o cliente? É visível em outros clientes?
kasperd
6
@ mike-m Parece que você encontrou um bug do NFS, provavelmente no servidor NFS. Isso ou corrupção do sistema de arquivos no servidor. Duvido que você possa realmente fazer outra coisa além de esperar que os administradores do servidor NFS lidem com isso.
30514 derobert

Respostas:

11

O seguinte trecho deste ensaio explica potencialmente por que esse diretório se recusa a ser excluído:

O NFSv4 exige que todos os nomes de arquivos sejam trocados usando UTF-8 pela conexão. A especificação NFSv4, RFC 3530, diz que os nomes de arquivos devem ser codificados em UTF-8 na seção 1.4.3: “Em uma partida ligeira, os nomes de arquivos e diretórios são codificados em UTF-8 para lidar com os princípios básicos da internacionalização.” O mesmo texto também é encontrado na seção 1.7.3 da NFS 4.1 RFC (RFC 5661) mais recente. O atual cliente NFS do Linux simplesmente passa os nomes dos arquivos diretamente, sem nenhuma conversão do código do idioma atual para e do UTF-8. Usar nomes de arquivos que não sejam UTF-8 pode ser um problema real em um sistema que usa um sistema NFSv4 remoto; qualquer servidor NFS que siga a especificação NFS deve rejeitar nomes de arquivos que não sejam UTF-8. Portanto, se você deseja garantir que seus arquivos possam realmente ser armazenados de um cliente Linux para um servidor NFS, você deve atualmente usar nomes de arquivos UTF-8. Em outras palavras,

UTF-8 é uma abordagem de longo prazo. Os sistemas precisam oferecer suporte ao UTF-8, bem como às muitas codificações mais antigas, dando às pessoas tempo para mudar para o UTF-8. Para usar “UTF-8 em qualquer lugar”, todas as ferramentas precisam ser atualizadas para oferecer suporte ao UTF-8. Anos atrás, esse era um grande problema, mas a partir de 2011 esse é essencialmente um problema resolvido, e acho que a trajetória é muito clara para esses poucos sistemas de rastreamento.

Nem todas as seqüências de bytes são UTF-8 legais e você não precisa descobrir como exibi-las. Se o kernel aplicar essas restrições, garantindo que apenas os nomes de arquivos UTF-8 sejam permitidos, não há problema ... todos os nomes de arquivos serão UTF-8 legais. A função utf8_check C de Markus Kuhn pode determinar rapidamente se uma sequência é UTF-8 válida.

O sistema de arquivos deve exigir que os nomes de arquivos atendam a algum padrão, não por causa de alguma necessidade maligna de controlar as pessoas, mas simplesmente para que os nomes sempre possam ser exibidos corretamente posteriormente. A falta de padrões torna as coisas mais difíceis para os usuários, não mais fáceis. No entanto, o sistema de arquivos não força os nomes de arquivos a serem UTF-8, portanto, pode facilmente ter lixo.

Timothy Martin
fonte
Isso parece ecoar a explicação dos administradores locais, vou marcar isso como a resposta da explicação dos administradores. Veja minha edição final
mike-m
19

Uma maneira de excluir arquivos / diretórios como esse é pela referência de inode.

Para encontrar os inodes para elementos no dir atual:

ls -i
14813568 mikeaâcnt

Para excluir isso:

find . -inum 14813568 -delete
Nicolai
fonte
veja a quinta edição.
Mike-m
4
Não, isso não exclui arquivos por seu inode. Isso procura um nome de arquivo para o inode fornecido e exclui o arquivo por seu nome. Não pode ajudar aqui, pois já foi feita uma tentativa com o nome correto (juntamente com outras tentativas com um nome incorreto).
Gilles 'SO- stop be evil'
@Gilles - tecnicamente, ele procura por um inode dentry e retorna um nome de arquivo, mas eu concordo.
mikeserv
11
@ Nicolai não está ajudando para mim. A mensagem Diretório não vazio é exibida.
diffracteD
11
Sim, hah, uma história engraçada sobre isso: o arquivo que estou tentando excluir tem ?como referência o inode. Como você o exclui então?
Nic Hartley
7

Você não deve usar caracteres não ASCII na linha de comando, pois, como você pode ver, por algum motivo, eles não corresponderão necessariamente ao nome do arquivo (o Unicode possui várias maneiras de expressar letras acentuadas). Algo como:

rm -rf mike*

deve funcionar, pois o nome do arquivo é gerado diretamente pelo shell. Mas verifique se há apenas uma correspondência (faça a echo mike*primeira para confirmar).

Bem, se cdfuncionar, não há razão para dizer rmou lsdizer No such file or directory, para que o problema possa estar no nível do sistema de arquivos.

Nota: Não use lspara descobrir se um diretório está vazio, mas ls -a.

O diretório ainda pode ser usado por outro processo (incluindo se é o cwd de algum processo). IMHO, é por isso que ainda "existe", mas pode gerar erros, por exemplo, com ls; lsofpode fornecer algumas informações, mas com o NFS, você precisa descobrir qual máquina a utiliza. Especialmente com o NFS, isso pode gerar erros estranhos. ls -ano diretório pai pode mostrar .nfs*arquivos / diretórios em alguns casos.

Quando você obtém:

$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

Eu suspeito que o arquivo ainda exista na tabela de diretórios devido ao cache do NFS e / ou porque é usado por outro processo, mas sem informações associadas. Quando lstenta obter informações sobre o próprio arquivo, ele recebe um erro, já que o arquivo em si não existe mais (está apenas na tabela de diretórios), daí o erro exibido. Em seguida, lsgera o nome do arquivo porque está na tabela de diretórios. O fato de você ter pontos de interrogação em um caso, mas não no outro, deve-se a um erro de exibição do lsIMHO (não relacionado ao seu problema).

vinc17
fonte
Eu já havia tentado um curinga antes, não funcionou, e eu falhei para deixar que a tentativa na minha pergunta, eu vou atualizar com o resultado
mike-m
Veja minha terceira edição. IMHO, isso se deve ao NFS (provavelmente não corrupção, mas cache incorreto) e possivelmente ao fato de outro processo estar usando o diretório. Em alguns casos, é preciso reiniciar tudo (o servidor e os clientes).
vinc17
Talvez isso possa explicar as coisas, mas não posso ter certeza, pois não tenho privilégios para retirá-lo para testes. Veja a quinta edição.
Mike-m
11
@ vinc17 favor, não use "Editar" na sua resposta, porque para novo leitor é que não faz sentido (já existe um histórico de edição)
Bernhard
iv adicionado alguma saída lsof, não tenho certeza se ele pode dizer-lhe qualquer coisa tho,
mike-m
3

Eu pessoalmente testei usando finda -execdiretiva:

$ mkdir -p mikeaâcnt
$ ls
mikeaâcnt
$ find -maxdepth 1 -type d -empty -exec rm -rf {} +
$ ls
$ 

A pasta foi criada e removida corretamente.

Como apontado por @Igeorget , há um método ainda mais simples se você tiver o GNU find:

$ find -maxdepth 1 -type d -empty -delete

Eu também testei este comando, e ele funciona corretamente

HalosGhost
fonte
E se você usar a localização do GNU, também há uma -deleteopção.
Lgeorget
Veja a 3ª edição,
mike-m
1

Eu tive o mesmo problema, acredito. Eu já vi o problema anteriormente com um nome de arquivo de . lsnesse caso, exibia o arquivo como â??, mas consegui excluí-lo com rm ☃.

Isso me levou à seguinte maneira de converter o nome errado para o correto:

Primeiro obtenha os bytes do nome do arquivo:

$ ls --show-control-chars | xxd
0000000: 6d69 6b65 61c3 a2c2 81c2 8463 6e74 0a    mikea......cnt.

Em seguida, decodifique esses bytes como UTF-8, para obter os pontos de código unicode, usando a entrada hexadecimal deste site, por exemplo: http://software.hixie.ch/utilities/cgi/unicode-decoder/utf8-decoder

U+006D LATIN SMALL LETTER M character
U+0069 LATIN SMALL LETTER I character
U+006B LATIN SMALL LETTER K character
U+0065 LATIN SMALL LETTER E character
U+0061 LATIN SMALL LETTER A character
U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX character (&#x00E2;)
U+0081 <control> character (&#x0081;)
U+0084 <control> character (&#x0084;)
U+0063 LATIN SMALL LETTER C character
U+006E LATIN SMALL LETTER N character
U+0074 LATIN SMALL LETTER T character

Observe que todos estão abaixo do limite de bytes. Obtemos os seguintes bytes:

6D 69 6B 65 61 E2 81 84 63 6E 74

Se tratarmos essa sequência no UTF-8, obtemos:

U+006D LATIN SMALL LETTER M character
U+0069 LATIN SMALL LETTER I character
U+006B LATIN SMALL LETTER K character
U+0065 LATIN SMALL LETTER E character
U+0061 LATIN SMALL LETTER A character
U+2044 FRACTION SLASH character (&#x2044;)
U+0063 LATIN SMALL LETTER C character
U+006E LATIN SMALL LETTER N character
U+0074 LATIN SMALL LETTER T character

E, portanto, seu nome de arquivo é:, mikea⁄cntcom uma barra de fração em vez de uma barra de avanço normal. Agora você pode passar esse nome para rmdir.

mvdnes
fonte
Isso é engenhoso, se eu encontrar isso de novo, vou manter isso em mente. um bom. +1
mike-m
0

Depois de obter o código hexadecimal correto do nome do arquivo / pasta (usando o método que achar melhor, posso escolher ls --show-control-chars | xxd), alguma construção especial deve ser usada para endereçar esses caracteres ao executar no bash:

rmdir $'mikea\xc3\xa2\xc2\x81\xc2\x84cnt'

Caso contrário, as barras invertidas são tratadas como barra invertida de baunilha.

Abel Cheung
fonte
Por favor, dê uma olhada no meu editar (8ª edição)
mike-m
@ mike-m Claro que isso não existe, porque lsinclui nova linha nos dados de saída e o "cnt" é duplicado. Talvez você possa copiar e colar diretamente a linha na minha resposta e ver se é eficaz.
Abel Cheung
Não, ainda assim: `` rl] $ rmdir $ 'mikea \ xc3 \ xa2 \ xc2 \ x81 \ xc2 \ x84cnt' rmdir: falha ao remover `mikeaâ \ 302 \ 201 \ 302 \ 204cnt ': nenhum arquivo ou diretório existe ``
mike-m
Nesse caso, é bem provável que seja uma combinação do problema do NFS e da localidade, impedindo que a maioria dos utilitários do sistema transmita bytes incorretos que não sejam UTF8. E parece que a remoção do inode piorou a situação. Por enquanto, a única maneira em que consigo pensar é definir seu sistema em um ambiente sem código de idioma (use o código de idioma "C" para variáveis ​​env LC_*e LANG) e monte o NFS sem nenhuma opção de conjunto de caracteres
Abel Cheung
0

Você já tentou usar rm -rf ./mikeaâcntou rm -rf "./mikeaâcnt"ou um caminho absoluto? Também em vez de rm, tente rmdir ./mikeaâcnt.

walsht
fonte
parte do problema é que os personagens mikeaâcntparecem não ser o nome do arquivo, mas o que ls é exibido, ver a 3ª edição
mike-m
0

Você tentou obter o inode desse arquivo com stat:

stat mike*

Isso deve fornecer o número do inode (e outros dados) e, em seguida, você pode tentar excluí-lo.

rsuarez
fonte
iv adicionou uma edição com statbehavour,
mike-m
0

Eu tive problemas semelhantes. Você tem Gnome, KDE ou algum tipo de Xwindow DM ?. Se você abrir o arquivo broser e remover o arquivo de lá.

Deveria funcionar.

Gostaria de ver uma solução na linha de comando, mas, no meu caso, e depois de perder muito tempo tentando descobrir como removê-la da linha de comando, achei que era tão simples quanto remover qualquer outro arquivo do nautilus ou qualquer outro explorador de arquivos (a verdade é que só tentei com o nautilus).

YoMismo
fonte