Como posso me livrar desse arquivo invisível?

6

Antecedentes

Eu tenho uma pasta chamada akorg✽ . Esse caractere Unicode causa dores de cabeça para mim quando o software faz suposições incorretas sobre a codificação de texto dos meus caminhos de arquivo, então eu gostaria de removê-lo do nome.

O problema

Você acha que isso seria fácil:

$ mv akorg✽ akorg
mv: cannot move ‘akorg✽’ to a subdirectory of itself, ‘akorg/akorg✽’

mas - isso é estranho - acha que já existe uma pasta chamada akorg . Tenho certeza que não há um:

$ ls -la
total 699K
drwxr-xr-x 15 ak ak   15 Jun 12 17:34 .
drwxr-xr-x 57 ak ak 4.0K Jun 12 17:35 ..
drwxr-xr-x 11 ak ak   21 Jun 12 16:58 akorg✽
drwxr-xr-x  2 ak ak    2 May 28 20:47 Desktop
...

Ainda assim, stat diz o contrário:

$ stat akorg
  File: ‘akorg’
  Size: 21          Blocks: 33         IO Block: 1536   directory
Device: 15h/21d Inode: 292128      Links: 11
...

Então, aparentemente, há uma pasta invisível no caminho. Seja como for, vou apenas removê-lo:

$ rmdir akorg
rmdir: failed to remove ‘akorg’: No such file or directory

Certo, então. O que no mundo é essa coisa?

O que eu sei até agora

  • Estou usando a versão estável do ZFS no Linux . Aqui está o zpool status e as propriedades do zfs .
  • stat retorna o mesmo inode para akorg e akorg✽ . A pesquisa por esse inode retorna apenas akorg✽ :

    $ find . -maxdepth 1 -inum 292128
    ./akorg✽
    
  • Mais coisas que não funcionam na pasta "invisível":

    $ rm akorg
    rm: cannot remove ‘akorg’: Is a directory
    $ unlink akorg
    unlink: cannot unlink ‘akorg’: Is a directory
    $ mv akorg akorg_temp
    mv: cannot move ‘akorg’ to ‘akorg_temp’: No such file or directory
    
  • Eu obtenho os mesmos resultados tanto no Bash 4.2.45 quanto no zsh 5.0.0. Em ambos, a conclusão de tabulação de ak retorna apenas akorg✽/ .
  • O strace da minha tentativa de renomeação inicial confirma que estou digitando os nomes corretamente e que a tentativa é frustrada pela preexistência de uma pasta chamada akorg .
  • Esta resposta a uma tentativa de renomeação mais explícita é intrigante e assustadora:

    $ mv --verbose --no-target-directory --no-clobber akorg✽ akorg
    removed ‘akorg✽’
    

    Eu não entendo porque ele diz ter removido akorg✽ , ou porque ele tentaria. Felizmente, ls e stat akorg akorg✽ revelam que nada realmente desapareceu. Aqui está o strace .

  • Para descartar as peculiaridades de codificação como causa disso, eu dei temporariamente akorg✽ um nome intermediário:

    $ mv --verbose --no-target-directory --no-clobber akorg✽ bananas
    ‘akorg✽’ -> ‘bananas’
    

    Isso funcionou como esperado,

    $ ls -la
    total 715K
    drwxr-xr-x 16 ak ak   16 Jun 13 15:11 .
    drwxr-xr-x 57 ak ak 4.0K Jun 13 14:03 ..
    drwxr-xr-x 11 ak ak   21 Jun 12 16:58 bananas
    drwxr-xr-x  2 ak ak    2 May 28 20:47 Desktop
    ...
    

    mas a pasta "invisível" ainda está presente:

    $ stat bananas akorg
      File: ‘bananas’
      Size: 21          Blocks: 33         IO Block: 1536   directory
    Device: 15h/21d Inode: 292128      Links: 11
    ...
      File: ‘akorg’
      Size: 21          Blocks: 33         IO Block: 1536   directory
    Device: 15h/21d Inode: 292128      Links: 11
    ...
    

    e mv ainda se comportam de maneira estranha quando tento usar o nome akorg :

    $ mv --verbose --no-target-directory --no-clobber bananas akorg
    removed ‘bananas’
    
por ændrük 13.06.2013 / 03:31

3 respostas

2

Isso é estranho. (E esta "resposta" começou como um comentário;), tornou-se um pouco longa para isso.)

Olhando para o strace parece que não há caracteres ocultos ou algo semelhante, senão eu suspeito que você teria visto em, por exemplo. (o que deveria ter resultado em -1 ENOENT e não em 0 se tudo estivesse OK):

stat("akorg", {st_mode=S_IFDIR|0755, st_size=21, ...}) = 0

como você faz em:

lstat("akorg245", {st_mode=S_IFDIR|0755, st_size=21, ...}) = 0

Entrou em uma troca de e-mails em que uma pessoa tem o problema oposto . ls listam os arquivos, mas statENOENT - embora isso esteja no FreeBSD.

Eu não sei muito sobre zfs , mas será que alguma sincronização, instantâneo ou algo parecido falhou e deixou uma tabela de arquivos corrompida? Você criou / tem um diretório chamado akorg que você excluiu antes de tentar o mv ?

Não sei se você pode obter algumas descrições de erros por:

# zpool status -v

Uma coisa é tentar verificar a consulta reversa do inode (opcionalmente, adicione outro d ) e verifique path :

# zdb -dddd <pool-name> <inode>

Em uma pasta chamada baz :

# zdb -dddd qqq 31
Object  lvl   iblk   dblk  dsize  lsize   %full  type
    31    1    16K    512     1K    512  100.00  ZFS directory
                                    264   bonus  ZFS znode
dnode flags: USED_BYTES USERUSED_ACCOUNTED 
dnode maxblkid: 0
path    /baz
uid     1000
gid     1000
atime   Fri Jun 14 12:39:46 2013
mtime   Fri Jun 14 11:55:33 2013
ctime   Fri Jun 14 11:55:33 2013
crtime  Fri Jun 14 11:55:33 2013
gen 1510
mode    40775
size    2
parent  3
links   2
xattr   0
rdev    0x0000000000000000
microzap: 512 bytes, 0 entries

Em um diretório chamado foo contendo vários subdiretórios, incluindo um chamado akorg✽ :

Object  lvl   iblk   dblk  dsize  lsize   %full  type
    16    1    16K    512     1K    512  100.00  ZFS directory
                                    264   bonus  ZFS znode
dnode flags: USED_BYTES USERUSED_ACCOUNTED 
dnode maxblkid: 0
path    /foo
uid     1000
gid     1000
atime   Fri Jun 14 13:10:38 2013
mtime   Fri Jun 14 12:13:18 2013
ctime   Fri Jun 14 12:13:18 2013
crtime  Fri Jun 14 11:41:53 2013
gen 1482
mode    40775
size    6
parent  3
links   6
xattr   0
rdev    0x0000000000000000
microzap: 512 bytes, 4 entries

    foo1 = 15 (type: Directory)
    foo2 = 18 (type: Directory)
    foo = 19 (type: Directory)
    akorg✽ = 30 (type: Directory)

As configurações que você tem em zfs get all storage/home-ak-annex para vários nomes de mods também parecem sãs (até onde eu sei) assim como as outras propriedades lendo Propriedades do ZFS :

storage/home-ak-annex  utf8only              off                    -
storage/home-ak-annex  normalization         none                   -
storage/home-ak-annex  casesensitivity       sensitive              -

Se você criar zfs você mesmo pode habilitar a depuração por ./configure --enable-debug e jogar com o acima, incluindo -vvvv , -bbbb etc.

Por fim, você pode abrir um novo problema no git.

    
por 14.06.2013 / 13:56
5

Como você está usando o zsh, eu recomendo a conclusão de tabulação ou globalização shell (sempre echo / ls antes de remover). Se isso não funcionar, você tem algumas opções:

Verifique seu nome de arquivo por meio de um dump hexadecimal e use $'...' para inseri-lo

% touch akorg✽   
% ls | grep akorg | hexdump -C
00000000  61 6b 6f 72 67 e2 9c bd  0a                       |akorg....|
00000009
% ls $'akorg\xe2\x9c\xbd'  
akorg✽
% rm $'akorg\xe2\x9c\xbd'
% ls
% 

Observe que o 0a final acima é a nova linha no final da entrada, por isso não queremos em nosso nome.

Use ls -i para obter o número do inode e use find para excluí-lo

% touch akorg✽
% ls -i
6128574 akorg✽
% find . -inum 6128574
akorg✽
% find . -inum 6128574 -delete
% ls
% 

Você também pode find pelo nome (de qualquer forma, imprimir primeiro!)

Use ls -b para obter o nome com escape e digite-o com $'...' (Isso funciona com caracteres não imprimíveis, mas não parece afetar seu unicode, portanto, isso é para a referência de outros).

% ls
foo?bar
% ls -b         
foo\rbar
% rm foo$'\r'bar
% ls
% 
    
por 13.06.2013 / 05:50
1

Eu estou supondo que você não tem um diretório invisível, mas sim que stat misprints os caracteres unicode para que o nome do arquivo pareça akorg quando na tela.

Duas soluções possíveis:

  1. Use um shell com conclusão de tabulação (zsh ou bash). No prompt, faça: rm -rf akorg<tab> . Zsh, pelo menos, completará o nome do arquivo, escapando caracteres especiais do shell, conforme necessário.

  2. Um forro, um pouco arriscado: rm -rf akorg?

Você pode fazer # 2 manualmente, algo como: ls -1 > filenames . Use algum editor de texto no arquivo chamado "nomes de arquivos" para excluir todas as linhas, exceto o diretório ofensivo. Adicione um prefixo de rm -rf a essa linha. Saia do editor. Execute como um script de shell: sh filenames

    
por 13.06.2013 / 04:08