Elegante Möglichkeit, mit Stückliste nach UTF-8-Dateien zu suchen?

94

Zum Debuggen muss ich rekursiv ein Verzeichnis nach allen Dateien durchsuchen, die mit einer UTF-8-Byte-Ordnungsmarke (BOM) beginnen. Meine aktuelle Lösung ist ein einfaches Shell-Skript:

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

Oder wenn Sie kurze, unlesbare Einzeiler bevorzugen:

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

Es funktioniert nicht mit Dateinamen, die einen Zeilenumbruch enthalten, aber solche Dateien sind sowieso nicht zu erwarten.

Gibt es eine kürzere oder elegantere Lösung?

Gibt es interessante Texteditoren oder Makros für Texteditoren?

vog
quelle

Antworten:

166

Was ist mit diesem einen einfachen Befehl, der die unangenehme Stückliste nicht nur findet, sondern löscht? :) :)

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

Ich liebe "finden" :)

Warnung Mit den obigen Anweisungen werden Binärdateien geändert, die diese drei Zeichen enthalten.

Wenn Sie nur Stücklistendateien anzeigen möchten, verwenden Sie diese:

grep -rl $'\xEF\xBB\xBF' .
Denis
quelle
9
Erkennt PDF mit einem Stücklistenmarker falsch. Das liegt daran, dass das gesamte Dokument durchsucht wird, nicht nur die erste Zeile
Olivier Refalo
1
Oder mit ack: "ack '\ xEF \ xBB \ xBF'"
Smar
5
Ändern Sie den Befehl sed, um eine 1 vor dem führenden 's' hinzuzufügen, sodass er nur für die erste Zeile gilt
Ben Combee
27
Verwenden Sie grep -rlI $'\xEF\xBB\xBF' .diese Option, um Binärdateien zu ignorieren.
Dbernard
1
Erkennt und ändert JPG und andere Binärdateien, wie bereits gesagt.
Jehy
41

Der beste und einfachste Weg, dies unter Windows zu tun:

Total Commander → gehe zum Stammverzeichnis des Projekts → finde Dateien ( Alt+F7 ) → Dateitypen *. * → Suchen Sie nach Text "EF BB BF" → Aktivieren Sie das Kontrollkästchen 'Hex' → Suchen

Und du bekommst die Liste :)

Jan Przybylo
quelle
4
Schön, besonders die Verwendung meines langjährigen Lieblings-Total-Kommandanten, aber leider hat dies das gleiche Problem wie viele andere: Es durchsucht alle Bytes in einem Fle, so viele Bilder usw. werden gemeldet. Dies kann leicht verbessert werden, indem RegEx anstelle von Hex verwendet wird und nach "^ \ xEF \ xBB \ xBF" gesucht wird, wodurch viele Bilder entfernt werden, aber immer noch Dateien vorhanden sind, deren Stückliste sich in der Mitte der Datei befindet (obwohl es nur wenige geben sollte), und natürlich Alle Binärdateien, die zufällig einen ASCII-Newline-Charcode haben, befinden sich nur vor der Stückliste. Trotzdem waren alle Bilder in meiner Testsuche verschwunden.
Legolas
13
find . -type f -print0 | xargs -0r awk '
    /^\xEF\xBB\xBF/ {print FILENAME}
    {nextfile}'

Die meisten der oben angegebenen Lösungen testen mehr als die erste Zeile der Datei, auch wenn einige (wie die Lösung von Marcus) die Ergebnisse filtern. Diese Lösung testet nur die erste Zeile jeder Datei, daher sollte sie etwas schneller sein.

Aron Griffis
quelle
1
Got arbeitet mit folgenden unter Linux (RHEL6) -find . -type f -print0 | xargs -0 awk '/^\xEF\xBB\xBF/ {print FILENAME} {nextfile}'
Olivier Refalo
Wie muss ich Ihren Code ändern, um diese Dateien zu reparieren, nachdem sie gefunden wurden?
Schwarz
7

Wenn Sie einige Fehlalarme akzeptieren (falls es keine Textdateien gibt oder im unwahrscheinlichen Fall ein ZWNBSP in der Mitte einer Datei), können Sie grep verwenden:

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

Ich würde so etwas verwenden wie:

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

Dadurch wird sichergestellt, dass die Stückliste ab dem ersten Byte der Datei erstellt wird.

Marcus Griep
quelle
5

Sie können sie verwenden grep, um sie zu finden, und Perl, um sie wie folgt zu entfernen:

grep -rl $'\xEF\xBB\xBF' . | xargs perl -i -pe 's{\xEF\xBB\xBF}{}'
Theorie
quelle
Dieser hat für mich funktioniert, die akzeptierte Antwort nicht (ich bin auf einem Mac)
mjsarfatti
4

Informationen für einen Windows-Benutzer finden Sie hier (gutes PHP-Skript zum Auffinden des BOMin Ihrem Projekt).

julien
quelle
Die verlinkte Website zeigt: "Website offline, keine zwischengespeicherte Version verfügbar".
Vog
Das gleiche Skript ist auch in github verfügbar: github.com/emrahgunduz/BomCleaner
emrahgunduz
Danke Kumpel, deine Antwort hat mir den Tag gerettet.
Krunal Panchal
Und ein Stücklisten-Finder: github.com/svn2github/wikia/blob/master/extensions/FCKeditor/… (falls jemand die "automatische" Reinigung nicht mag oder nur die Dateien mit Stückliste finden möchte)
meloniq
3

Eine Overkill-Lösung hierfür ist phptags(nicht das gleichnamige viTool), das speziell nach PHP-Skripten sucht:

phptags --warn ./

Gibt etwas aus wie:

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

Und der --whitespaceModus behebt solche Probleme automatisch (rekursiv, behauptet jedoch, dass nur .php-Skripte neu geschrieben werden.)

Mario
quelle
2
find -type f -print0 | xargs -0 grep -l `printf '^\xef\xbb\xbf'` | sed 's/^/found BOM in: /'
  • find -print0 Setzt zwischen jedem Dateinamen eine Null \ 0, anstatt neue Zeilen zu verwenden
  • xargs -0 erwartet null getrennte Argumente anstelle von zeilengetrennten
  • grep -l listet die Dateien auf, die dem regulären Ausdruck entsprechen
  • Der ^\xeff\xbb\xbfreguläre Ausdruck ist nicht ganz korrekt, da er mit UTF-8-Dateien ohne BOMed übereinstimmt, wenn sie am Anfang einer Zeile Leerzeichen mit einer Breite von Null haben
Jonathan Wright
quelle
Sie benötigen noch einen "Kopf 1" in der Pipe vor dem grep
MSalters
2

Ich habe dies verwendet, um nur JavaScript-Dateien zu korrigieren:

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

Wenn Sie nach UTF-Dateien suchen, funktioniert der Befehl file . Hier erfahren Sie, wie die Codierung der Datei lautet. Wenn sich dort Nicht-ASCII-Zeichen befinden, wird UTF angezeigt.

file *.php | grep UTF

Das wird aber nicht rekursiv funktionieren. Sie können wahrscheinlich einen ausgefallenen Befehl erstellen, um ihn rekursiv zu machen, aber ich habe jede Ebene einzeln wie folgt durchsucht, bis mir die Ebenen ausgegangen sind.

file */*.php | grep UTF
Mike Dotterer
quelle