identifica arquivos com caracteres não-ASCII ou não-imprimíveis no nome do arquivo

21

Em um tamanho de diretório de 80 GB com aproximadamente 700.000 arquivos, há alguns nomes de arquivo com caracteres não ingleses no nome do arquivo. Além de vasculhar a lista de arquivos, está laboriosamente:

  • Uma maneira fácil de listar ou identificar esses nomes de arquivos?
  • Uma maneira de gerar caracteres imprimíveis do idioma não inglês - os caracteres que não estão listados no intervalo imprimível de man ascii (para testar se esses arquivos estão sendo identificados)?
por suspectus 17.01.2014 / 11:29

3 respostas

28

Assumindo que "foreign" significa "não é um caractere ASCII", você pode usar find com um padrão para localizar todos os arquivos que não possuem caracteres ASCII imprimíveis em seus nomes:

LC_ALL=C find . -name '*[! -~]*'

(O espaço é o primeiro caractere imprimível listado no link , ~ é o último.)

A dica para LC_ALL=C é necessária (na verdade, LC_CTYPE=C e LC_COLLATE=C ), caso contrário, o intervalo de caracteres é interpretado incorretamente. Veja também a página de manual glob(7) . Como LC_ALL=C faz com que find interprete strings como ASCII, ele imprimirá caracteres de múltiplos bytes (como π ) como pontos de interrogação. Para corrigir isso, canalize para algum programa (por exemplo, cat ) ou redirecione para o arquivo.

Em vez de especificar intervalos de caracteres, [:print:] também pode ser usado para selecionar "caracteres imprimíveis". Certifique-se de definir o código do idioma C ou obter um comportamento bastante (aparentemente) arbitrário.

Exemplo:

$ touch $(printf '\u03c0') "$(printf 'x\ty')"
$ ls -F
dir/  foo  foo.c  xrestop-0.4/  xrestop-0.4.tar.gz  π
$ find -name '*[! -~]*'       # this is broken (LC_COLLATE=en_US.UTF-8)
./x?y
./dir
./π
... (a lot more)
./foo.c
$ LC_ALL=C find . -name '*[! -~]*'
./x?y
./??
$ LC_ALL=C find . -name '*[! -~]*' | cat
./x y
./π
$ LC_ALL=C find . -name '*[![:print:]]*' | cat
./x y
./π
    
por 17.01.2014 / 12:12
6

Se você traduzir cada nome de arquivo usando tr -d '[0-7]' e compará-lo com o nome original, então qualquer nome de arquivo que tenha caracteres especiais não será o mesmo.

(O acima, supondo que você quer dizer não-ASCII com estrangeiros)

    
por 17.01.2014 / 12:11
3

Você pode usar tr para excluir qualquer caractere estrangeiro de um nome de arquivo e comparar o resultado com o nome do arquivo original para ver se ele continha caracteres estrangeiros.

find . -type f > filenames
while read filename; do
      stripped="$(printf '%s\n' "$filename" | tr -d -C '[[:alnum:]][[:space:]][[:punct:]]')"
      test "$filename" = "$stripped" || printf '%s\n' "$filename"; 
done < filenames
    
por 17.01.2014 / 12:12