Un moyen élégant de rechercher des fichiers UTF-8 avec BOM?


94

À des fins de débogage, je dois rechercher de manière récursive dans un répertoire tous les fichiers commençant par une marque d'ordre d'octet (BOM) UTF-8. Ma solution actuelle est un simple script shell:

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

Ou, si vous préférez des one-liners courts et illisibles:

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

Cela ne fonctionne pas avec les noms de fichiers contenant un saut de ligne, mais de tels fichiers ne sont pas attendus de toute façon.

Existe-t-il une solution plus courte ou plus élégante?

Existe-t-il des éditeurs de texte intéressants ou des macros pour les éditeurs de texte?

Réponses:


166

Qu'en est-il de cette simple commande qui non seulement trouve mais efface la mauvaise nomenclature? :)

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

J'adore "trouver" :)

Avertissement Ce qui précède modifiera les fichiers binaires contenant ces trois caractères.

Si vous souhaitez simplement afficher les fichiers de nomenclature, utilisez celui-ci:

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

9
Détecte incorrectement le PDF avec un marqueur de nomenclature ... c'est parce qu'il recherche tout le document, pas seulement la première ligne
Olivier Refalo

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

5
changez la commande sed pour ajouter un 1 avant le 's' de tête afin qu'il ne s'applique qu'à la première ligne
Ben Combee

27
Utilisez grep -rlI $'\xEF\xBB\xBF' .pour ignorer les fichiers binaires.
dbernard

1
Détecte et modifie JPG et autres fichiers binaires, comme déjà dit.
Jehy

41

La meilleure et la plus simple façon de procéder sous Windows:

Total Commander → aller dans le répertoire racine du projet → rechercher des fichiers ( Alt+ F7) → types de fichiers *. * → Rechercher le texte "EF BB BF" → cocher la case 'Hex' → rechercher

Et vous obtenez la liste :)


4
Bien, en particulier l'utilisation de mon commandant Total préféré de longue date, mais malheureusement, cela souffre du même problème que beaucoup d'autres: il recherche tous les octets d'un fichier, tant d'images, etc. Cela peut être légèrement amélioré en utilisant RegEx au lieu de Hex et en recherchant "^ \ xEF \ xBB \ xBF" qui éliminera de nombreuses images mais contient toujours des fichiers dont la nomenclature est à mi-chemin du fichier (bien qu'il devrait y en avoir peu) et bien sûr tous les fichiers binaires qui ont un charcode ascii newline juste avant la nomenclature. Pourtant, toutes les images avaient disparu dans ma recherche de test.
Legolas

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

La plupart des solutions données ci-dessus testent plus que la première ligne du fichier, même si certaines (comme la solution de Marcus) filtrent alors les résultats. Cette solution ne teste que la première ligne de chaque fichier, elle devrait donc être un peu plus rapide.


1
Got travaille avec ce qui suit sur Linux (RHEL6) -find . -type f -print0 | xargs -0 awk '/^\xEF\xBB\xBF/ {print FILENAME} {nextfile}'
Olivier Refalo

Comment dois-je modifier votre code pour corriger ces fichiers une fois qu'ils ont été trouvés?
Noir

7

Si vous acceptez des faux positifs (dans le cas où il y aurait des fichiers non texte, ou dans le cas peu probable il y aurait un ZWNBSP au milieu d'un fichier), vous pouvez utiliser grep:

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

5

J'utiliserais quelque chose comme:

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

Ce qui garantira que la nomenclature se produit à partir du premier octet du fichier.


5

Vous pouvez utiliser greppour les trouver et Perl pour les supprimer comme ceci:

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

Celui-ci a fonctionné pour moi, la réponse acceptée n'a pas fonctionné (je suis sur un Mac)
mjsarfatti

4

Pour un utilisateur Windows, voyez ceci (bon script PHP pour trouver le BOMdans votre projet).


Le site Web lié affiche: "Site Web hors ligne, aucune version mise en cache disponible".
vog le

même script est également disponible dans github: github.com/emrahgunduz/BomCleaner
emrahgunduz

Merci mon pote, ta réponse a sauvé ma journée.
Krunal Panchal

Et un BOM Finder: github.com/svn2github/wikia/blob/master/extensions/FCKeditor/… (au cas où quelqu'un n'aime pas le nettoyage `` automatique '', ou veut simplement trouver les fichiers avec BOM)
meloniq

3

Une solution exagérée à cela est phptags(pas l' vioutil du même nom), qui recherche spécifiquement les scripts PHP:

phptags --warn ./

Sortira quelque chose comme:

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

Et le --whitespacemode résoudra automatiquement ces problèmes (récursivement, mais affirme qu'il ne réécrit que les scripts .php.)


2
find -type f -print0 | xargs -0 grep -l `printf '^\xef\xbb\xbf'` | sed 's/^/found BOM in: /'
  • find -print0 met un null \ 0 entre chaque nom de fichier au lieu d'utiliser de nouvelles lignes
  • xargs -0 attend des arguments séparés par des valeurs nulles au lieu d'être séparés par des lignes
  • grep -l répertorie les fichiers qui correspondent à l'expression régulière
  • Le regex ^\xeff\xbb\xbfn'est pas tout à fait correct, car il correspondra aux fichiers UTF-8 non-BOMed s'ils n'ont aucun espace de largeur au début d'une ligne

Vous avez encore besoin d'un "head 1" dans le tube avant le grep
MSalters

2

J'ai utilisé ceci pour corriger uniquement les fichiers JavaScript:

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

0

Si vous recherchez des fichiers UTF, la commande de fichier fonctionne. Il vous dira quel est l'encodage du fichier. S'il y a des caractères non ASCII, il apparaîtra avec UTF.

file *.php | grep UTF

Cela ne fonctionnera pas de manière récursive. Vous pouvez probablement configurer une commande sophistiquée pour la rendre récursive, mais j'ai juste recherché chaque niveau individuellement comme suit, jusqu'à ce que je manque de niveaux.

file */*.php | grep UTF
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.