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?

vog
la source

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

Jan Przybylo
la source
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.

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

Marcus Griep
la source
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}{}'
théorie
la source
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).

Julien
la source
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.)

mario
la source
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
Jonathan Wright
la source
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 \;
Affinero
la source
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
Mike Dotterer
la source