Utilizando find ou grep para localizar nomes de arquivos com caracteres acentuados de um sistema de codificação diferente (Windows para Linux)

5

Eu tentei marcar tarde para uma pergunta semelhante à minha em stackoverflow ( Localizar nomes de arquivo não-UTF8 no sistema de arquivos do Linux ) para obter mais respostas, sem sorte até agora, então aqui vai novamente ...

Eu tenho o mesmo problema que o OP no link acima e o convmv é uma ótima ferramenta para consertar o próprio sistema de arquivos. Minha pergunta é, portanto, acadêmica, mas acho insatisfatório (na verdade, não posso acreditar) que 'encontrar' não é capaz de encontrar caracteres ascii não padrão.

Existe alguém por aí que saiba qual combinação de opções usar para encontrar nomes de arquivos que contenham caracteres não padrão no que parece ser um FS unicode, no meu caso os caracteres parecem ser 8bits ascii em vez de unicode, o arquivos vêm de uma máquina Windows (iso-8859-1) e eu regularmente preciso buscá-los. Eu adoraria ver como find e / ou grep podem fazer o mesmo que convmv.

Arquivos de amostra:

> ls
Abc�def ÉÈéèáà-rest everest éverest

> ls -b
Abc1def  ÉÈéèáà-rest  everest  éverest

O primeiro arquivo vem do Windows (ou simulado com touch $(printf "Abc\xA9def") ).

> find . -regex '.*[^a-zA-Z./].*'
./ÉÈéèáà-rest

> ls | egrep '[^a-zA-Z]'
ÉÈéèáà-rest

Faltando quase todos eles (o hífen salvou esse arquivo, pode ser visto com grep colorido). O que quer que esteja acontecendo aqui não é o que eu esperaria: nem encontrar nem grep é capaz de levar uma letra acentuada como estando fora do intervalo fornecido [^ a-zA-Z ./].

> find . -regex '.*é.*'
./éverest
./ÉÈéèáà-rest

> ls | egrep 'é'
ÉÈéèáà-rest
éverest

> ls | egrep '[é]'
ÉÈéèáà-rest
éverest

> find . -regex '.*[é].*'
./éverest
./ÉÈéèáà-rest

Bizarramente, ambos são capazes de captar um acento padrão quando fornecidos (inclusive no intervalo). Qualquer tentativa de encontrar ou grep com \ xA9, \ 0251 ou \ o251 falhará (sem correspondência).

> ls | fgrep e
Abc�def
ÉÈéèáà-rest
everest
éverest

A procura por um caracter não controverso mostra todos os arquivos com o grep, como eu esperava.

> find . -regex '.*e.*'
./éverest
./ÉÈéèáà-rest
./everest

> find . -name '*e*'
./éverest
./ÉÈéèáà-rest
./everest

encontrar, no entanto, é muito discriminatório: mesmo procurando um caractere normal, parece-me que elimina nomes de arquivos que contêm caracteres fora do intervalo de caracteres aceitáveis para o esquema de codificação de nomes do sistema de arquivos.

Tanto quanto eu estou preocupado se o arquivo está no sistema de arquivos, então encontrar deve encontrá-lo, certo? Mas talvez haja um recurso que eu não conheça?

Qualquer ideia seria muito apreciada.

    
por asoundmove 06.12.2010 / 01:37

3 respostas

8

As ferramentas GNU parecem ter código que faz com que as letras acentuadas sejam tratadas como suas letras de base ao corresponderem a uma classe de caracteres regex, se suportadas pela codificação de caracteres. Este é um tipo de recurso "faça o que eu quero dizer" para facilitar a criação de regexes, mas, neste caso, está atrapalhando.

Tente a seguinte modificação na sua linha de comando "encontrar":

LANG=C find . -regex '.*[^a-zA-Z./].*'

Isso define a variável de ambiente LANG somente no contexto do comando "find". Como a codificação da linguagem "C" suporta somente ASCII, as letras acentuadas não serão mais tratadas como suas letras de base e, portanto, serão correspondidas adequadamente pelo seu regex.

    
por 06.12.2010 / 02:07
5

A resposta de Jander faz o trabalho perfeitamente, para aqueles interessados em tirar mais proveito disso, aqui está mais uma dica.

Com LANG = C, find exibe caracteres não-ascii com pontos de interrogação. Para converter isso de volta para sua exibição normal com esse sistema de arquivos, basta enviar a saída para cat.

LANG=C find . -regex '.*[^a-zA-Z./-].*'
./??verest
./????????????-rest
./Abc?def

LANG=C find . -regex '.*[^a-zA-Z./-].*' | cat
./éverest
./ÉÈéèáà-rest
./Abc�def
    
por 06.12.2010 / 03:09
0
find . | grep -E '.*[^[:print:]].*'

Para uma lista de todas as classes de caracteres posix, consulte: link

    
por 15.11.2015 / 13:59