it-swarm.com.de

Wie kann man prüfen, ob es sich um eine Binärdatei handelt, und alle Dateien lesen, die keine sind?

Woher weiß ich, ob es sich bei einer Datei um eine Binärdatei handelt?

Zum Beispiel kompilierte c-Datei.

Ich möchte alle Dateien aus einem Verzeichnis lesen, aber ich möchte Binärdateien ignorieren.

38
Refael

Verwenden Sie das Dienstprogramm file. Verwendungsbeispiel:

 $ file /bin/bash
 /bin/bash: Mach-O universal binary with 2 architectures
 /bin/bash (for architecture x86_64):   Mach-O 64-bit executable x86_64
 /bin/bash (for architecture i386): Mach-O executable i386

 $ file /etc/passwd
 /etc/passwd: ASCII English text

 $ file code.c
 code.c: ASCII c program text

file Handbuchseite

43
Adam Siemion

Angepasst aus ausschließlich Binärdatei

find . -exec file {} \; | grep text | cut -d: -f1
9
gongzhitaao

Ich benutze

! grep -qI . $path

Der einzige Nachteil, den ich sehen kann, ist, dass eine leere Datei als Binärdatei betrachtet wird. Aber wer entscheidet, ob dies falsch ist?

8
Alois Mahdal
Perl -E 'exit((-B $ARGV[0])?0:1);' file-to-test

Kann verwendet werden, um zu überprüfen, wann "file-to-test" binär ist. Der obige Befehl wird mit Code 0 für Binärdateien beendet, andernfalls lautet der Beendigungscode 1.

Die umgekehrte Prüfung für Textdateien kann folgendermaßen aussehen:

Perl -E 'exit((-T $ARGV[0])?0:1);' file-to-test

Ebenso wird der obige Befehl mit Status 0 beendet, wenn die "zu testende Datei" Text ist (nicht binär).

Lesen Sie mehr über die -B- und -T-Prüfungen mit dem Befehl perldoc -f -X.

4
Onlyjob

BSD grep

Hier ist eine einfache Lösung, um nach einer einzelnen Datei mit BSD grep (unter macOS/Unix) zu suchen:

grep -q "\x00" file && echo Binary || echo Text

im Grunde wird geprüft, ob die Datei NUL-Zeichen enthält.

Wenn Sie mit dieser Methode alle nicht-binären Dateien rekursiv mit dem Dienstprogramm find lesen, können Sie Folgendes tun:

find . -type f -exec sh -c 'grep -q "\x00" {} || cat {}' ";"

Oder noch einfacher mit grep:

grep -rv "\x00" .

Verwenden Sie für nur den aktuellen Ordner:

grep -v "\x00" *

Leider funktionieren die obigen Beispiele nicht für GNU grep , es gibt jedoch eine Problemumgehung.

GNU grep

Da GNU grep NULL-Zeichen ignoriert, ist es möglich, nach anderen Nicht-ASCII-Zeichen zu suchen wie:

$ grep -P "[^\x00-\x7F]" file && echo Binary || echo Text

Hinweis: Es funktioniert nicht für Dateien, die nur NULL-Zeichen enthalten.

3
kenorb

Verwenden Sie den in Perl integrierten -T Datei-Testoperator, vorzugsweise nachdem Sie festgestellt haben, dass es sich um eine reine Datei handelt, und verwenden Sie den -f Datei-Operator:

$ Perl -le 'for (@ARGV) { print if -f && -T }' \
    getwinsz.c a.out /etc/termcap /bin /bin/cat \
    /dev/tty /usr/share/zoneinfo/UTC /etc/motd
getwinsz.c
/etc/termcap
/etc/motd

Hier ist die Ergänzung dieses Sets:

$ Perl -le 'for (@ARGV) { print unless -f && -T }' \
    getwinsz.c a.out /etc/termcap /bin /bin/cat \
    /dev/tty /usr/share/zoneinfo/UTC /etc/motd
a.out
/bin
/bin/cat
/dev/tty
/usr/share/zoneinfo/UTC
2
tchrist

Versuchen Sie die folgende Befehlszeile:

file "$FILE" | grep -vq 'ASCII' && echo "$FILE is binary"
1
user1985553

cat + grep

Angenommen, binär bedeutet, dass die Datei NULL-Zeichen enthält. Dieser Shell-Befehl kann dabei helfen:

(cat -v file.bin | grep -q "\^@") && echo Binary || echo Text

oder:

grep -q "\^@" <(cat -v file.bin) && echo Binary

Dies ist die Problemumgehung für grep -q "\x00" , die für BSD grep funktioniert, nicht jedoch für die Version GNU.

Grundsätzlich konvertiert -v für cat alle nicht druckbaren Zeichen so, dass sie in Form von Steuerzeichen sichtbar sind. Beispiel:

$ printf "\x00\x00" | hexdump -C
00000000  00 00                                             |..|
$ printf "\x00\x00" | cat -v
^@^@
$ printf "\x00\x00" | cat -v | hexdump -C
00000000  5e 40 5e 40                                       |^@^@|

dabei stehen ^@-Zeichen für NULL-Zeichen. Sobald diese Steuerzeichen gefunden wurden, gehen wir davon aus, dass die Datei binär ist.


Der Nachteil des obigen Verfahrens besteht darin, dass es falsch positive Ergebnisse erzeugen kann, wenn Zeichen keine Steuerzeichen darstellen. Zum Beispiel:

$ printf "\x00\x00^@^@" | cat -v | hexdump -C
00000000  5e 40 5e 40 5e 40 5e 40                           |^@^@^@^@|

Siehe auch: Wie grep ich für alle Nicht-ASCII-Zeichen .

1
kenorb

Ausgehen Bachs Vorschlag , ich denke, --mime-encoding ist die beste Flagge, um etwas zuverlässiges von file zu erhalten.

file --mime-encoding [FILES ...] | grep -v '\bbinary$'

druckt die Dateien, von denen file eine nicht-binäre Kodierung erwartet. Sie können diese Ausgabe über cut -d: -f1 weiterleiten, um den : encoding abzuschneiden, wenn Sie nur die Dateinamen verwenden möchten.


Einschränkung: Da @yugr-Berichte unter .doc-Dateien eine Kodierung von application/mswordbinary melden. Das sieht für mich wie ein Fehler aus - der Mime-Typ wird fälschlicherweise mit der Kodierung verkettet.

$ for flag in --mime --mime-type --mime-encoding; do
    echo "$flag"
    file "$flag" /tmp/example.{doc{,x},png,txt}
  done
--mime
/tmp/example.doc:  application/msword; charset=binary
/tmp/example.docx: application/vnd.openxmlformats-officedocument.wordprocessingml.document; charset=binary
/tmp/example.png:  image/png; charset=binary
/tmp/example.txt:  text/plain; charset=us-ascii
--mime-type
/tmp/example.doc:  application/msword
/tmp/example.docx: application/vnd.openxmlformats-officedocument.wordprocessingml.document
/tmp/example.png:  image/png
/tmp/example.txt:  text/plain
--mime-encoding
/tmp/example.doc:  application/mswordbinary
/tmp/example.docx: binary
/tmp/example.png:  binary
/tmp/example.txt:  us-ascii
1
dimo414

Vielleicht würde das ausreichen ..

if ! file /path/to/file | grep -iq ASCII ; then
    echo "Binary"
fi

if file /path/to/file | grep -iq ASCII ; then
    echo "Text file"
fi
0
Mike Q

Es ist eine Art rohe Gewalt, binäre Dateien mit tr -d "[[:print:]\n\t]" < file | wc -c auszuschließen, aber es ist auch keine heuristische Vermutung.

find . -type f -maxdepth 1 -exec /bin/sh -c '
   for file in "[email protected]"; do
      if [ $(LC_ALL=C LANG=C tr -d "[[:print:]\n\t]" < "$file" | wc -c) -gt 0 ]; then
         echo "${file} is no ASCII text file (UNIX)"
      else
         echo "${file} is ASCII text file (UNIX)"
      fi
   done
' _ '{}' +

Der folgende Brute-Force-Ansatz mit grep -a -m 1 $'[^[:print:]\t]' file scheint jedoch etwas schneller zu sein.

find . -type f -maxdepth 1 -exec /bin/sh -c '
   tab="$(printf "\t")"
   for file in "[email protected]"; do
      if LC_ALL=C LANG=C grep -a -m 1 "[^[:print:]${tab}]" "$file" 1>/dev/null 2>&1; then
         echo "${file} is no ASCII text file (UNIX)"
      else
         echo "${file} is ASCII text file (UNIX)"
      fi
   done
' _ '{}' + 
0
vron

grep

Angenommen, binär bedeutet Datei, die nicht druckbare Zeichen enthält (mit Ausnahme von Leerzeichen wie Leerzeichen, Tabulatoren oder neuen Zeilenzeichen). Dies kann funktionieren (sowohl BSD als auch GNU)

$ grep '[^[:print:][:blank:]]' file && echo Binary || echo Text

Hinweis: GNU grep meldet eine Datei, die nur NULL-Zeichen als Text enthält, funktioniert aber unter BSD-Version ordnungsgemäß.

Weitere Beispiele finden Sie unter: Wie grep ich für alle Nicht-ASCII-Zeichen .

0
kenorb

Sie können dies auch tun, indem Sie den Befehl diff verwenden. Überprüfen Sie diese Antwort:

https://unix.stackexchange.com/questions/275516/is-there-a-venven-way-to-classify-files-as-binary-or-text#answer-402870

0
tonix