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.
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
adapté de à l'exclusion du fichier binaire
find . -exec file {} \; | grep text | cut -d: -f1
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?
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
.
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.
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
essayez la ligne de commande suivante:
file "$FILE" | grep -vq 'ASCII' && echo "$FILE is binary"
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 .
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
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
' _ '{}' +
vous pouvez faire cela aussi en utilisant la commande diff
. Cochez cette réponse:
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 .