Maneira elegante de pesquisar arquivos UTF-8 com BOM?


94

Para fins de depuração, preciso pesquisar recursivamente em um diretório todos os arquivos que começam com uma marca de ordem de bytes (BOM) UTF-8. Minha solução atual é um script de shell simples:

find -type f |
while read file
do
    if [ "`head -c 3 -- "$file"`" == $'\xef\xbb\xbf' ]
    then
        echo "found BOM in: $file"
    fi
done

Ou, se você preferir linhas curtas e ilegíveis:

find -type f|while read file;do [ "`head -c3 -- "$file"`" == $'\xef\xbb\xbf' ] && echo "found BOM in: $file";done

Não funciona com nomes de arquivo que contenham uma quebra de linha, mas de qualquer maneira esses arquivos não são esperados.

Existe alguma solução mais curta ou mais elegante?

Existem editores de texto ou macros interessantes para editores de texto?

Respostas:


166

Que tal este comando simples que não apenas encontra, mas limpa o BOM desagradável? :)

find . -type f -exec sed '1s/^\xEF\xBB\xBF//' -i {} \;

Eu amo "encontrar" :)

Aviso O acima irá modificar os arquivos binários que contêm esses três caracteres.

Se você deseja apenas mostrar arquivos BOM, use este:

grep -rl $'\xEF\xBB\xBF' .

9
Detecta PDF incorretamente com um marcador BOM .. isso porque ele pesquisa todo o documento, não apenas a primeira linha
Olivier Refalo

1
Ou com ack: "ack '\ xEF \ xBB \ xBF'"
Smar

5
mude o comando sed para adicionar 1 antes do 's' para que ele se aplique apenas à primeira linha
Ben Combee

27
Use grep -rlI $'\xEF\xBB\xBF' .para ignorar arquivos binários.
dbernard

1
Detecta e modifica JPG e outros arquivos binários, como já foi dito.
Jehy

41

A maneira melhor e mais fácil de fazer isso no Windows:

Total Commander → vá para o diretório raiz do projeto → encontre arquivos ( Alt+ F7) → tipos de arquivo *. * → Encontre o texto "EF BB BF" → marque a caixa de seleção 'Hex' → pesquisar

E você obtém a lista :)


4
Legal, especialmente o uso do meu comandante Total favorito de longa data, mas infelizmente ele sofre o mesmo problema que muitos outros: ele pesquisa todos os bytes em um arquivo, tantas imagens, etc, são relatadas. Isso pode ser um pouco melhorado usando RegEx em vez de Hex e procurando por "^ \ xEF \ xBB \ xBF", o que eliminará muitas imagens, mas ainda possui arquivos com o BOM no meio do arquivo (embora deva haver poucos) e, claro quaisquer arquivos binários que tenham um charcode de nova linha ascii apenas antes do BOM. Ainda assim, todas as imagens desapareceram na minha pesquisa de teste.
Legolas,

13
find . -type f -print0 | xargs -0r awk '
    /^\xEF\xBB\xBF/ {print FILENAME}
    {nextfile}'

A maioria das soluções fornecidas acima testa mais do que a primeira linha do arquivo, mesmo que algumas (como a solução de Marcus) filtrem os resultados. Esta solução testa apenas a primeira linha de cada arquivo, portanto, deve ser um pouco mais rápida.


1
Got está trabalhando com o seguinte no Linux (RHEL6) -find . -type f -print0 | xargs -0 awk '/^\xEF\xBB\xBF/ {print FILENAME} {nextfile}'
Olivier Refalo

Como devo modificar seu código para corrigir esses arquivos depois que eles forem encontrados?
Preto de

7

Se você aceitar alguns falsos positivos (no caso de haver arquivos que não sejam de texto, ou no caso improvável de haver um ZWNBSP no meio de um arquivo), você pode usar grep:

fgrep -rl `echo -ne '\xef\xbb\xbf'` .

5

Eu usaria algo como:

grep -orHbm1 "^`echo -ne '\xef\xbb\xbf'`" . | sed '/:0:/!d;s/:0:.*//'

O que garantirá que o BOM ocorra começando no primeiro byte do arquivo.


5

Você pode usar greppara encontrá-los e Perl para removê-los assim:

grep -rl $'\xEF\xBB\xBF' . | xargs perl -i -pe 's{\xEF\xBB\xBF}{}'

Este funcionou para mim, a resposta aceita não (estou em um Mac)
mjsarfatti

4

Para um usuário do Windows, veja isto (bom script PHP para encontrar o BOMem seu projeto).


O site vinculado mostra: "Site off-line, nenhuma versão em cache disponível".
vog

o mesmo script também está disponível no github: github.com/emrahgunduz/BomCleaner
emrahgunduz

Obrigado amigo, sua resposta salvou meu dia.
Krunal Panchal

E um localizador de BOM: github.com/svn2github/wikia/blob/master/extensions/FCKeditor/… (caso alguém não goste da limpeza 'automática' ou apenas queira encontrar os arquivos com BOM)
meloniq

3

Uma solução exagerada para isso é phptags (não a viferramenta com o mesmo nome), que procura especificamente por scripts PHP:

phptags --warn ./

Irá produzir algo como:

./invalid.php: TRAILING whitespace ("?>\n")
./invalid.php: UTF-8 BOM alone ("\xEF\xBB\xBF")

E o --whitespacemodo corrigirá automaticamente esses problemas (recursivamente, mas afirma que só reescreve scripts .php).


2
find -type f -print0 | xargs -0 grep -l `printf '^\xef\xbb\xbf'` | sed 's/^/found BOM in: /'
  • find -print0 coloca um nulo \ 0 entre cada nome de arquivo em vez de usar novas linhas
  • xargs -0 espera argumentos separados por nulos em vez de separados por linha
  • grep -l lista os arquivos que correspondem ao regex
  • O regex ^\xeff\xbb\xbfnão está totalmente correto, pois corresponderá a arquivos UTF-8 não BOMed se eles tiverem espaços de largura zero no início de uma linha

Você ainda precisa de uma "cabeça 1" no tubo antes do grep
MSalters

2

Usei isso para corrigir apenas arquivos JavaScript:

find . -iname *.js -type f -exec sed 's/^\xEF\xBB\xBF//' -i.bak {} \; -exec rm {}.bak \;

0

Se você estiver procurando por arquivos UTF, o comando file funciona. Ele dirá qual é a codificação do arquivo. Se houver algum caractere não ASCII nele, ele aparecerá com UTF.

file *.php | grep UTF

Isso não funcionará recursivamente. Você provavelmente pode montar algum comando sofisticado para torná-lo recursivo, mas eu apenas procurei cada nível individualmente como o seguinte, até que os níveis acabaram.

file */*.php | grep UTF
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.