Como remover caracteres inválidos de nomes de arquivos?

44

Eu tenho arquivos com caracteres inválidos como estes

009_-_�%86ndringshåndtering.html

É um Æ em que algo deu errado no nome do arquivo.

Existe uma maneira de remover apenas todos os caracteres inválidos?

ou poderia tr ser usado de alguma forma?

echo "009_-_�%86ndringshåndtering.html" | tr ???
    
por Sandra 10.01.2012 / 14:07

8 respostas

40

Um caminho seria com o sed:

mv 'file' $(echo 'file' | sed -e 's/[^A-Za-z0-9._-]/_/g')

Substitua file pelo seu nome de arquivo, é claro. Isso substituirá qualquer coisa que não seja uma letra, um número, um período, um sublinhado ou um traço com um sublinhado. Você pode adicionar ou remover caracteres para mantê-lo como quiser e / ou alterar o caractere de substituição para qualquer outra coisa ou nada.

    
por 10.01.2012 / 14:22
30

Suponho que você esteja na caixa do Linux e os arquivos foram criados em uma caixa do Windows. O Linux usa o UTF-8 como codificação de caracteres para nomes de arquivos, enquanto o Windows usa outra coisa. Eu acho que essa é a causa do problema.

Eu usaria "convmv". Esta é uma ferramenta que pode converter nomes de arquivos de uma codificação de caracteres para outro. Para a Europa Ocidental, um deles normalmente funciona:

convmv -r -f windows-1252 -t UTF-8 .
convmv -r -f ISO-8859-1 -t UTF-8 .
convmv -r -f cp-850 -t UTF-8 .

Se você precisar instalá-lo em um Linux baseado em Debian, pode fazê-lo executando:

sudo apt-get install convmv

Funciona para mim todas as vezes e recupera o nome do arquivo original.

Fonte: LeaseWebLabs

    
por 25.12.2013 / 00:23
15

Eu suponho que você quer dizer que quer percorrer o sistema de arquivos e consertar todos esses arquivos?

Aqui está o jeito que eu faria

find /path/to/files -type f -print0 | \
perl -n0e '$new = $_; if($new =~ s/[^[:ascii:]]/_/g) {
  print("Renaming $_ to $new\n"); rename($_, $new);
}'

Isso localizaria todos os arquivos com caracteres não ascii e substituiria esses caracteres por sublinhados ( _ ). Tenha cuidado, porém, se um arquivo com o novo nome já existir, ele irá sobrescrevê-lo. O script pode ser modificado para verificar esse caso, mas não coloquei isso para mantê-lo simples.

    
por 10.01.2012 / 14:41
13

Seguindo as respostas em link , você pode usar:

rename 's/[^\x00-\x7F]//g' *

em que * corresponde aos arquivos que você deseja renomear. Se você quiser fazer isso em vários diretórios, você pode fazer algo como:

find . -exec rename 's/[^\x00-\x7F]//g' "{}" \;

Você pode usar o argumento -n para rename para fazer uma execução a seco e ver o que seria alterado sem alterá-lo.

    
por 25.05.2015 / 10:52
8

Eu tinha alguns arquivos em japonês com nomes de arquivos quebrados recuperados de um stick usb quebrado e as soluções acima não funcionaram para mim.

Eu recomendo o pacote de desintoxicação:

The detox utility renames files to make them easier to work with. It removes spaces and other such annoyances. It'll also translate or cleanup Latin-1 (ISO 8859-1) characters encoded in 8-bit ASCII, Unicode characters encoded in UTF-8, and CGI escaped characters.

Exemplo de uso:

detox -r -v /path/to/your/files
-r Recurse into subdirectories
-v Be verbose about which files are being renamed 
-n Can be used for a dry run (only show what would be changed)
    
por 30.08.2017 / 06:57
5

Este script de shell limpa um diretório recursivamente, para tornar os arquivos portáveis entre o Linux / Windows e o FAT / NTFS / exFAT. Remove caracteres de controle, /:*?"<>\| e alguns nomes reservados do Windows como COM0 .

sanitize() {
  shopt -s extglob;

  filename=$(basename "$1")
  directory=$(dirname "$1")

  filename_clean=$(echo "$filename" | sed -e 's/[\/:\*\?"<>\|\x01-\x1F\x7F]//g' -e 's/^\(nul\|prn\|con\|lpt[0-9]\|com[0-9]\|aux\)\(\.\|$\)//i' -e 's/^\.*$//' -e 's/^$/NONAME/')

  if (test "$filename" != "$filename_clean")
  then
    mv -v "$1" "$directory/$filename_clean"
  fi
}

export -f sanitize

sanitize_dir() {
  find "$1" -depth -exec bash -c 'sanitize "$0"' {} \;
}

sanitize_dir '/path/to/somewhere'

O Linux é menos restritivo na teoria ( / e * são estritamente proibidos em nomes de arquivos) mas na prática vários caracteres interferem nos comandos bash (como %code% ...) então eles também devem ser evitados em nomes de arquivos.

Ótimas fontes para restrições de nomes de arquivos:

por 11.05.2016 / 20:50
1

Se você quiser lidar com novas linhas incorporadas, caracteres multibyte, espaços, traços iniciais, barras invertidas e espaços, você precisará de algo mais robusto, veja esta resposta: link

Eu coloquei o script em code.google.com se alguém estiver interessado: rnf-bash- renomear script

    
por 31.12.2014 / 00:09
-2

para arquivo em *; do mv "$ arquivo" $ (echo "$ arquivo" | sed -e 's / [^ A-Za-z0-9. -] / / g'); feito &

    
por 04.07.2017 / 21:53

Tags