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?

vog
fonte

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' .
Denis
fonte
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 :)

Jan Przybylo
fonte
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.

Aron Griffis
fonte
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'` .
CesarB
fonte
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.

Marcus Griep
fonte
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}{}'
teoria
fonte
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).

julien
fonte
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).

mario
fonte
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
Jonathan Wright
fonte
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 \;
Refineo
fonte
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
Mike Dotterer
fonte