Comment vérifier si le fichier est un fichier binaire et lire tous les fichiers qui ne le sont pas?

Comment savoir si un fichier est un fichier binaire?

par exemple, fichier c compilé.

je veux lire tous les fichiers d'un répertoire, mais je veux ignorer les fichiers binaires.

36
demandé sur kenorb 2013-05-26 18:49:29

12 réponses

Utilisation de l'utilitaire file , exemple d'utilisation:

 $ 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 "page de manuel

40
répondu Adam Siemion 2013-05-26 14:57:02

adapté de à l'exclusion du fichier binaire

find . -exec file {} \; | grep text | cut -d: -f1
9
répondu gongzhitaao 2013-05-26 15:47:00

j'utilise

! grep -qI . $path

Seul inconvénient que je vois c'est qu'il envisagera d'un fichier vide binaire mais là encore, qui décide si c'est faux?

8
répondu Alois Mahdal 2016-12-10 01:54:08
perl -E 'exit((-B $ARGV[0])?0:1);' file-to-test

peut être utilisé pour vérifier chaque fois que" file-to-test " est binaire. La commande ci-dessus va sortir le code wit 0 sur les fichiers binaires, sinon le code de sortie serait 1.

la vérification inverse du fichier texte peut ressembler à la commande suivante:

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

de même, la commande ci-dessus quittera avec l'état 0 si le" fichier à tester " est du texte (Pas binaire).

plus d'informations à propos des contrôles -B et -T en utilisant la commande perldoc -f -X .

4
répondu Onlyjob 2013-09-09 09:06:00

BSD grep

Voici une solution simple pour vérifier un fichier unique en utilisant BSD grep (sur macOS/Unix):

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

qui vérifie si le fichier est composé D'un caractère NUL.

en utilisant cette méthode, pour lire tous les fichiers non binaires récursivement en utilisant find utilitaire, vous pouvez faire:

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

ou encore plus simple en utilisant juste grep :

grep -rv "\x00" .

pour juste le dossier courant, utilisez:

grep -v "\x00" *

malheureusement les exemples ci-dessus ne fonctionneront pas pour GNU grep , cependant il y a une solution.

GNU grep

puisque GNU grep ignore les caractères nuls, il est possible de vérifier pour les autres caractères non ASCII comme:

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

Note: cela ne fonctionnera pas pour les fichiers contenant seulement des caractères nuls.

3
répondu kenorb 2018-04-12 21:48:48

utilisez L'opérateur de test de fichier -T intégré à Perl, de préférence après s'être assuré qu'il s'agit d'un fichier simple en utilisant l'opérateur de test de fichier -f :

$ 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

voici le complément de cet ensemble:

$ 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
répondu tchrist 2013-06-18 22:42:02

essayez la ligne de commande suivante:

file "$FILE" | grep -vq 'ASCII' && echo "$FILE is binary"
1
répondu user1985553 2015-05-08 16:49:00

cat + grep

en supposant que binaire signifie le fichier contenant des caractères nuls, cette commande shell peut aider:

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

ou:

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

c'est la solution pour grep -q "\x00" , qui fonctionne pour BSD grep, mais pas pour la version GNU.

essentiellement -v pour cat convertit tous les caractères non imprimants de sorte qu'ils sont visible sous forme de caractères de contrôle, par exemple:

$ 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                                       |^@^@|

où les caractères ^@ représentent le caractère nul. Donc, une fois que ces caractères de contrôle sont trouvés, nous supposons que le fichier est binaire.


l'inconvénient de la méthode ci-dessus est qu'elle peut générer des faux positifs lorsque les caractères ne représentent pas les caractères de contrôle. Par exemple:

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

voir aussi: Comment puis-je noter tous les caractères non-ASCII .

1
répondu kenorb 2018-04-12 21:51:56

Going off suggestion de Bach , je pense que --mime-encoding est le meilleur drapeau pour obtenir quelque chose de fiable de file .

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

affichera les fichiers dont file pense qu'ils ont un encodage non binaire. Vous pouvez utiliser cut -d: -f1 pour couper le : encoding si vous voulez simplement les noms de fichiers.


mise en garde: as @yugr rapporte ci-dessous Les fichiers .doc rapportent un encodage de application/mswordbinary . Cela me semble être un bug - le type mime est concaténé par erreur avec l'encodage.

$ 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
répondu dimo414 2018-07-23 21:31:21

c'est une sorte de force brute pour exclure les fichiers binaires avec tr -d "[[:print:]\n\t]" < file | wc -c , mais ce n'est pas non plus une supposition heuristique.

find . -type f -maxdepth 1 -exec /bin/sh -c '
   for file in "$@"; 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
' _ '{}' +

l'approche de force brute suivante utilisant grep -a -m 1 $'[^[:print:]\t]' file semble un peu plus rapide, cependant.

find . -type f -maxdepth 1 -exec /bin/sh -c '
   tab="$(printf "\t")"
   for file in "$@"; 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
répondu vron 2014-02-21 13:01:53

vous pouvez faire cela aussi en utilisant la commande diff . Cochez cette réponse:

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

0
répondu tonix 2017-11-06 16:49:19

grep

en supposant que le fichier binaire signifie un fichier contenant des caractères non imprimables (à l'exclusion des caractères Vierges tels que les espaces, les onglets ou les caractères de nouvelle ligne), cela peut fonctionner (à la fois BSD et GNU):

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

Note: GNU grep rapportera fichier contenant seulement des caractères nuls comme texte, mais il fonctionnerait correctement sur version BSD .

Pour plus d'exemples, voir: Comment puis-je grep pour tous les caractères non-ASCII .

0
répondu kenorb 2018-04-12 22:27:36