Não é possível excluir / mover arquivos com caracteres especiais no nome do arquivo

16

Como você pode ver abaixo, os arquivos têm caracteres incomuns.

Excluí-los no terminal ou o Dolphin retorna o erro:

  

Nenhum arquivo ou diretório desse tipo

A execução de ls -la no diretório me deu esta saída:

-rw-rw-r--  1 aalap aalap      0 Nov 14 01:05 ??
-rw-rw-r--  1 aalap aalap      0 Nov 14 01:05 ?2?.???љ?!?Gb??σ?[?F?
-rw-rw-r--  1 aalap aalap      0 Nov 14 01:05 ??3]d???:????????1????G?p?ȋ??????嫳?d????ą-??
-rw-rw-r--  1 aalap aalap      0 Nov 14 01:05 3l??#g?w????O?JKB7?co??քH??bT?NA???S???X?I?A?qC??M?I???
-rw-rw-r--  1 aalap aalap      0 Nov 14 01:05 ??8??-?@,?Zp?[?bI????7^?ñ[?ڏ??z?O???ч??eEȰ?+??,OF??h

Eu executei um comando fsck na partição de outro sistema operacional, mas isso não mudou nada.

Como faço para remover esses arquivos?

    
por karjedavpalaa 30.12.2017 / 18:46

2 respostas

34

Uma maneira simples seria remover esses arquivos por seu inode. :)

Use ls -li no diretório com os caracteres incomuns para mostrar o número de inode de cada arquivo, por exemplo,

$ ls -li
total 0
133370 -rw-r--r-- 1 malte malte 0 Dec 30 19:00 ?2?.???љ?!?Gb??σ?[?F?
132584 -rw-r--r-- 1 malte malte 0 Dec 30 18:59 ??3]d???:????????1????G?p?ȋ??????嫳?d????ą-??

Em seguida, use o utilitário find para excluir o arquivo correspondente pelo nome, usando a sintaxe find <somepath> -inum <inode_number> -exec rm -i {} \; , como no exemplo a seguir:

$ find . -inum 133370 -exec rm -i {} \;
rm: remove regular empty file ‘./?2?.???љ?!?Gb??σ?[?F?’? y
$ ls -li
total 0
132584 -rw-r--r-- 1 malte malte 0 Dec 30 18:59 ??3]d???:????????1????G?p?ȋ??????嫳?d????ą-??

A opção -i para rm não é realmente necessária, apenas a adicionei para evitar que você remova acidentalmente arquivos que não pretendia remover. :) Isso faz com que rm peça confirmação para cada arquivo que você deseja excluir.

Se você quiser remover vários arquivos de seus inodes, use a sintaxe -o (significando ou ) para find :

$ find .  \( -inum 133370 -o -inum 132584 \) -exec rm -i {} \;
rm: remove regular empty file ‘./?2?.???љ?!?Gb??σ?[?F?’? y
rm: remove regular empty file ‘./??3]d???:????????1????G?p?ȋ??????嫳?d????ą-??’? y

Você pode adicionar mais números de inode estendendo a expressão entre parênteses com mais expressões -o -inum <inode_number> .

    
por Malte Skoruppa 30.12.2017 / 19:04
13

É importante entender que isso não é o tipo de "corrupção do sistema de arquivos" que fsck irá ajudar. No que diz respeito ao sistema de ficheiros, os nomes dos ficheiros podem ser qualquer sequência de bytes , desde que nenhum byte possua o valor 0x00 (ASCII NUL, marcador de fim de cadeia C) ou 0x2F ( / , o separador de diretório). (Se um nome de arquivo de alguma forma tiver um byte 00 ou 2F incorporado, fsck deve corrigir isso.)

Em vez disso, o que você tem são nomes de arquivo que o software do aplicativo (Dolphin, ls ) acha que contêm caracteres que são não exibíveis em seu "código do idioma", substituindo-os por caracteres de espaço reservado . Você não pode digitar esses caracteres, então manipular os arquivos é mais difícil, mas você pode fazê-lo contanto que você o faça sem nunca digitar ou copiar e colar o nome. Por exemplo, se você excluir ou renomear os arquivos problemáticos diretamente do Dolphin, isso deve Just Work (eu diria que, se não funcionar, isso é um bug no Dolphin).

Se você precisar fazer algo sobre eles a partir do shell (por exemplo, se eles são de propriedade de root e, portanto, não podem ser modificados por um programa GUI), você pode nomear indiretamente usando padrões "glob", que ser expandido para a (s) sequência (s) correta (s) de bytes e repassado.

Agora, é claro, você não desejaria excluir as coisas por acidente porque seu padrão glob correspondia muito, então minha recomendação seria usar o utilitário Perl rename para converter cada nome de arquivo em sua codificação hexadecimal:

$ rename '$_ = unpack("H*", $_)' *

Isso não destrói nenhuma informação - nem o arquivo em si, nem qualquer significado originalmente codificado no nome do arquivo antes de ser destroçado. Pode ser desfeito para arquivos específicos com, por exemplo,

$ rename '$_ = pack("H*", $_)' 696d706f7274616e742e646f63

Cuidado: existem dois programas chamados rename , de diferentes origens; os comandos acima só funcionarão com o originador do Perl. No Ubuntu, o que você quer é o do pacote "rename", não aquele do pacote "util-linux". rename -h vai distinguir: é isso que você quer ...

$ rename -h
Usage:
    rename [ -h|-m|-V ] [ -v ] [ -n ] [ -f ] [ -e|-E perlexpr]*|perlexpr
    [ files ]
# ...

... isso não é o que você quer ...

$ rename -h

Usage:
 rename [options] <expression> <replacement> <file>...
# ...

A principal coisa a procurar é "perlexpr". Você pode ter uma versão mais antiga da renomeação do Perl que não entende todas as opções acima, mas o comando que mostrei ainda deve funcionar.

Editar: Em 14.04 .5 o script em perl incluído para rename não suporta o parâmetro -h. Você pode confirmar que tem a correta, marcando a página man com man rename e, nesse caso, a linha superior conterá:

  

RENAME (1) Manual de referência de programadores Perl RENAME (1)

    
por zwol 30.12.2017 / 23:56