Standard-Unix-Dienstprogramme mögen grep
und diff
verwenden eine Heuristik, um Dateien als "Text" oder "Binär" zu klassifizieren. (Eg grep
's Ausgabe kann Zeilen wie enthalten Binary file frobozz matches
.)
Gibt es einen bequemen Test, den man in einem zsh
Skript anwenden kann , um eine ähnliche "Text / Binär" -Klassifizierung durchzuführen? (Anders als so etwas grep '' somefile | grep -q Binary
.)
(Mir ist klar, dass ein solcher Test notwendigerweise heuristisch und daher unvollkommen wäre.)
file
ist ein Standard-Dienstprogramm und kann die Dateimagie nach besten Kräften durchlaufen, um Dateitypen zu bestimmen. Es kann die meisten Textformate erkennen und leistet bei Binärformaten ziemlich gute Arbeit. Wenn Sie nur herausfindenfile
werden gedruckt, z. B.shell script
für einige Dateien, die ich als "Text" klassifizieren möchte. Gibt es eine Möglichkeit,file
einfach zu druckentext
oderbinary
?cut
Befehle.file
Ausgabe zurcut
Lösung ist - sicher, dass es einen fehlenden Platz gibt, der zum Fehlschlagen führt, und das hat dazu geführt Die meisten Leute dort sprechen das Y anstelle des X an, aber Stéphanes Kommentare und Antworten zeigen die richtige Art und Weise, um festzustellen, ob es sich bei der Datei um Text handelt oder nicht.Antworten:
Wenn Sie fragen ,
file
um nur den MIME-Typ Sie viele verschiedene, wie zu bekommentext/x-shellscript
, undapplication/x-executable
etc, aber ich glaube , wenn Sie nur für den „Text“ Teil überprüfen sollten Sie gute Ergebnisse erzielen. ZB (-b
für keinen Dateinamen in der Ausgabe):quelle
file
, dass Sie vielleicht einige Textformate verpassen:application/xml
(und ähnlich wie RSS)application/ecmascript
,application/json
,image/svg+xml
, ... Sie müssten die weiße Liste diejenigen.application/*
Typen nicht für den menschlichen Verzehr bestimmt, auch wenn sie möglicherweise textbasiert sind, um die Entwicklung und das Debuggen zu erleichtern. Deshalb gibt es sowohl eintext/xml
als auch einapplication/xml
. Die Frage, ob sie als Text betrachtet werden sollen, hängt also von den Bedürfnissen des OP ab.cut -d/ -f1
Ein anderer Ansatz wäre die Verwendung
isutf8
aus der moreutils- Sammlung.Es wird mit 0 beendet, wenn die Datei UTF-8 oder ASCII gültig ist, oder es werden Kurzschlüsse ausgegeben, eine Fehlermeldung ausgegeben (Stille mit
-q
) und ansonsten mit 1 beendet.quelle
Wenn Ihnen die von GNU verwendete Heuristik gefällt
grep
, können Sie sie verwenden:Es sucht nach NUL-Bytes im ersten Puffer, der aus der Datei gelesen wird (einige Kilobytes für eine reguläre Datei, aber viel weniger für eine Pipe oder einen Socket oder ähnliche Geräte
/dev/random
). In UTF-8-Ländereinstellungen werden auch Byte-Sequenzen markiert, die keine gültigen UTF-8-Zeichen bilden. Es wird davonLC_ALL
ausgegangen, dass die Sprache nicht Englisch ist.Mit dem
${1-$REPLY}
Formular können Sie es alszsh
Glob-Qualifikationsmerkmal verwenden:würde die Binärdateien auflisten.
quelle
Sie können versuchen, festzustellen, ob
iconv
die Datei gelesen werden kann. Dies ist weniger performant alsfile
(das liest nur ein paar Bytes von Anfang an), liefert aber zuverlässigere Ergebnisse:Dies ist im
iconv
Grunde genommen ein No-Op, aber wenn es auf ungültige Daten stößt (ungültiges UTF-8 in diesem Beispiel), wird es gesperrt und beendet.quelle
-f
und-t
anstelle der GNU long-Optionen würde es portabler machen. Beachten Sie, dass es die Dateien "binär" nennt, die es nicht öffnen kann. Leere Dateien werden als "Text" bezeichnet.iconv
. Aber-f
und-t
sind meistens besser.Sie können ein Skript schreiben, das aufruft
file
, und mithilfe einer case-Anweisung prüfen, an welchen Fällen Sie interessiert sind.Beispielsweise
Natürlich kann es viele Sonderfälle geben, die von Interesse sind. Wenn ich nur
strings
eine Kopie von ansehelibmagic
, sehe ich ungefähr 200 Fälle, zBEinige verwenden die Zeichenfolge "Text" als Teil eines anderen Typs, z.
script
könnte ebenfalls Teil eines Wortes sein, aber ich sehe in diesem Fall keine Probleme. Ein Skript sollte jedoch nach"text"
einem Wort suchen , nicht nach einer Teilzeichenfolge .Zur Erinnerung, die
file
Ausgabe verwendet keine genaue Beschreibung, die immer "Skript" oder "Text" enthalten würde. Sonderfälle sind zu berücksichtigen. Ein Follow-up kommentierte, dass der--mime-type
Ansatz zwar nicht funktioniert, für.svg
Dateien. In einem Test sehe ich jedoch die folgenden Ergebnisse für svg-Dateien:Die ich nach dem Betrachten von tausend Dateien ausgewählt habe, zeigen nur 6 mit "Text" in der MIME-Typ-Ausgabe. Argumentieren, am Ende der MIME-Typ Ausgabe nützlicher sein könnte , die „xml“ passend, sagt, als matching „SVG“, aber mit einem Skript zu tun , dass bringen Sie zurück auf den Vorschlag hier gemacht.
Die Ausgabe von
file
erfordert einige Anpassungen in beiden Szenarien und ist nicht 100% zuverlässig (es wird von mehreren meiner Perl-Skripten verwirrt und nennt sie "Daten").Es gibt mehr als eine Implementierung von
file
. Das am häufigsten verwendete erledigt seine Arbeit inlibmagic
, das von verschiedenen Programmen aus verwendet werden kann (vielleicht nicht direkt vonzsh
, obwohlpython
kann).Gemäß der Vergleichstabelle für Dateitests für Shell, Perl, Ruby und Python verfügt Perl über eine
-T
Option, mit der diese Informationen bereitgestellt werden können. Es listet aber keine vergleichbare Funktion fürzsh
.Weitere Lektüre:
quelle
file
Ausgabe von GNU für svg-Dateien: denSVG Scalable Vector Graphics image
Worttext nicht. Ich dachte, dieser Ansatz wäre besser als die akzeptierte Antwort, den MIME-Typ zu überprüfen, aber es fehlen immer noch einige Typen.image/svg+xml
. Eigentlich - habe gerade eine 1000-Datei gleich überprüft, nur 6 kamen als "Text" laut MIME-Typ alleine heraus. Ich halte mich an ein Skript, das zumindest nach Bedarf zum Laufen gebracht werden kann.file
hat eine Option--mime-encoding
, die versucht, die Codierung einer Datei zu erkennen.Sie können
file --mime-encoding | grep binary
feststellen, ob es sich bei einer Datei um eine Binärdatei handelt. Es funktioniert zuverlässig, obwohl es durch ein einzelnes ungültiges Zeichen in einer langen Textdatei verwirrt werden kann.Ich habe beispielsweise einen Alias
cat
für das folgende Shell-Skript, um zu vermeiden, dass mein Terminal versehentlich durch Öffnen einer Binärdatei zerstört wird:quelle
Kategorien sind beliebig. Bevor Sie eine Klassifizierung vornehmen, benötigen Sie eine (strenge) Definition. Um eine Definition zu haben, brauchen Sie einen Zweck .
Also, was willst du mit dieser Klassifizierung machen?
quelle
werde es tun. Siehe Dokumentation für
-B
und-T
(suchen Sie auf dieser Seite nach der ZeichenfolgeThe -T and -B switches work as follows
).quelle
perl -le 'print -B $ARGV[0] ? "binary" : "text"' --
könnte klarer sein. Oder sogarperl -le 'print -B $_ ? "binary" : "text", @ARGV > 1 ? "\t$_" : "" for @ARGV' --
Ich habe zu https://github.com/audreyr/binaryornot beigetragen. Es gibt (noch) keinen Befehlszeilen-Wrapper, aber dies ist eine einfache Python-Bibliothek, die auch von der CLI aus leicht aufzurufen ist. Es wird eine ziemlich effiziente Heuristik verwendet, um festzustellen, ob es sich bei einer Datei um Text oder um eine Binärdatei handelt.
quelle
Ich habe jetzt diese Antwort ein bisschen alt, aber ich denke, mein Freund hat mir einen tollen "Hack" beigebracht, um dies zu tun.
Sie verwenden den
diff
Befehl und überprüfen Ihre Datei anhand einer Testtextdatei:$ diff filetocheck testfile.txt
Wenn
filetocheck
es sich nun um eine Binärdatei handelt, wäre die Ausgabe:Binary files filetocheck and testfile.txt differ
Auf diese Weise können Sie den
diff
Befehl nutzen und z. B. eine Funktion schreiben, die das Einchecken eines Skripts vornimmt.quelle