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

17

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

captura de tela do gerenciador de arquivos

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

Não existe tal arquivo ou diretório

A execução ls -lano 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 fsckcomando na partição de outro sistema operacional, mas isso não mudou nada.

Como faço para remover esses arquivos?

karjedavpalaa
fonte
1
Você configurou seu sistema para ter um diretório pessoal criptografado?
Dobey #
@ Dobey eu não.
karjedavpalaa
5
@ Panther Você está enganado. Isso não é , por si só, uma indicação de um sistema de arquivos corrompido e, mesmo que tenha sido causado por algum tipo de corrupção de dados, o fsck não fará nada a respeito.
Zwol
1
Eu tive arquivos com caracteres não reconhecidos no nome. Renomeando os arquivos funcionados. então eles podem ser excluídos.
Ravery

Respostas:

35

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

Use ls -lino diretório com 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 findutilitário para excluir o arquivo correspondente por seu 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 -iopção para rmnão é realmente necessária, eu apenas a adicionei para impedir que você acidentalmente remova arquivos que não pretendia remover. :) Faz com rmque solicite confirmação para cada arquivo que você deseja excluir.

Se você deseja remover vários arquivos por seus inodes, pode usar a sintaxe -o(meaning or ) 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 -o -inum <inode_number>expressões.

Malte Skoruppa
fonte
4
Que tal rm -ri .?
Brent Baccala
Isso funcionou: encontre <somepath> -inum <inode_number> -exec rm -i {} \; O que '-inum', '{}' e '\' fazem no comando?
karjedavpalaa
Como faço para remover vários arquivos de uma só vez? Além disso, obrigado, você fez o meu dia!
karjedavpalaa
2
@BrentBaccala rm -ri .não está excluindo arquivos por inode, no entanto. Ele simplesmente percorre todo o diretório de trabalho e solicita cada arquivo se você deseja removê-lo - e você precisa estar muito atento aos arquivos que está solicitando para não remover acidentalmente os indesejados. Eu certamente não gostaria de usar este comando para o meu diretório pessoal - ele contém MUITOS arquivos. ;)
Malte Skoruppa
3
@karjedavpalaa (1) -inumdiz findpara procurar arquivos pelo número de inode. (2) {}corresponde ao (s) arquivo (s) encontrado (s) por grep. (3) \ escapa o ;símbolo que termina o comando passado para a -execopção de find. (4) Editei minha resposta para explicar como remover vários arquivos de uma só vez.
Malte Skoruppa
13

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

Em vez disso, o que você tem são nomes de arquivos que o software aplicativo (Dolphin ls) acham que contêm caracteres que não são exibidos no seu "código do idioma", por isso os substitui por caracteres de espaço reservado. Você também não pode digitar esses caracteres, portanto, manipular os arquivos é mais difícil, mas você pode fazê-lo desde que sem digitar ou copiar e colar o nome. Por exemplo, se você excluir ou renomear os arquivos com problemas diretamente no Dolphin, isso deve funcionar (eu diria que, se não funcionar, é um bug no Dolphin).

Se você precisar fazer algo sobre eles a partir do shell (por exemplo, se eles pertencem roote, portanto, não podem ser modificados por um programa GUI), você pode nomeá-los indiretamente usando padrões "glob", que serão expandidos para a sequência correta (s) de bytes e transmitidos.

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

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

Isso não destrói nenhuma informação - nem o próprio arquivo, nem qualquer significado que possa ter sido originalmente codificado no nome do arquivo antes de ser confundido. Pode ser desfeito para arquivos específicos com

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

Cuidado: existem dois programas nomeados rename, de origens diferentes; os comandos acima funcionarão apenas com o originado no Perl. No Ubuntu, o que você deseja é aquele do pacote "renomear", não o pacote "util-linux". rename -hvai distinguir: é isso que você quer ...

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

... não é isso 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 do renomear Perl que não entende todas as opções acima, mas o comando que eu mostrei ainda deve funcionar.

Edit: Sob 14.04 .5, o script perl incluído para renamenão suporta a opção -h. Você pode confirmar que possui a correta, verificando sua página de manual e man rename, nesse caso, a linha superior conterá:

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

zwol
fonte
renomear --version Opção desconhecida: versão
Elder Geek
@ElderGeek O que file $(which rename)imprime? (Certifique-se de ter o filepacote instalado, em primeiro lugar.)
Zwol
/usr/bin/rename: symbolic link to /etc/alternatives/rename( fileÉ instalado por padrão) Na verdade você tem que perseguir os links simbólicos para chegar /usr/bin/file-rename: a /usr/bin/perl -w script, ASCII text executable , mas man renameé uma indicação mais rápido ...
Elder Geek
@ElderGeek Se é um script perl, provavelmente é uma versão mais antiga do "originário do Perl", que não suporta --version; o comando que sugeri ainda deve funcionar. (/usr/share/doc/rename/changelog.gz no meu computador, que executa o Debian instável, indica que --versionfoi adicionado na versão 0.10 da renomeação do Perl, em 2013. Estou surpreso que o Ubuntu ainda esteja enviando algo mais antigo que isso, mas este programa não tem realmente mudou a sua funcionalidade (!) desde 2007 por isso é bom).
Zwol
Ah! Isso explica a confusão. Apesar de muitas alegações em contrário, o Debian não é o Ubuntu. Não posso falar em todas as versões, mas algumas versões atualmente suportadas do Ubuntu LTS (14.04) ainda não têm isso. (Embora 16.04 o faça)
Elder Geek