2013-05-26 16 views
34

Come posso sapere se un file è un file binario?Come verificare se il file è un file binario e leggere tutti i file che non lo sono?

Ad esempio, file c compilato.

Voglio leggere tutti i file da qualche directory, ma voglio ignorare i file binari.

+8

definitiva * tutti i file * sono binari. I file di testo contengono solo rappresentazioni binarie di dati di caratteri leggibili dall'uomo. Nessun metodo per distinguere il testo da non-testo può essere affidabile al 100%. –

+0

[Simile a Vim.] (Http://vi.stackexchange.com/q/3206/467) – kenorb

risposta

35

Utilizzare l'utilità file, l'utilizzo del campione:

$ 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 manual page

+4

Considerare l'utilizzo di "file --mine". Per i file binari riporta "... charset = binary", quindi si può semplicemente grep per il regexp "binary $". – 4dan

+8

@ 4dan - forse '--mime'? :) – Bach

+0

@ 4dan Funziona per me: 'file -bL --mime" $ ​​path "| grep -q '^ text''. L'opzione '-b' rimuove il nome del file dall'output e' -L' dereferences symlink. – wjandrea

8

Adattato da excluding binary file

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

Questo dovrebbe essere 'grep text'; storicamente, 'file' non diceva sempre ASCII, ma piuttosto" testo script di shell "per esempio. – Jens

+0

@Jens Grazie per avermelo ricordato. Basta controllare la manpage 'file', dovrebbe essere' text'. – gongzhitaao

+0

Ho appena realizzato che ha reinventato la ruota ancora una volta: per il file in 'find. -type f -exec file {} \; | testo di grep | perl -nle 'split /: /; print $ _ [0]' '; fai grep -i --color 'string_to_search' $ file; fatto ; –

2

Utilizzo di Perl built-in -T file di operatore di verifica, preferibilmente dopo aver accertato che si tratta di un file semplice utilizzando l'operatore di prova file -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 

Ecco il complemento di quel set:

$ 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 
3
perl -E 'exit((-B $ARGV[0])?0:1);' file-to-test 

Potrebbe essere usato per controllare ogni volta che "il file-to-test" è binario. Il comando precedente codice di uscita di spirito 0 su file binari, altrimenti il ​​codice di uscita sarebbe 1.

Il controllo d'inversione per file di testo può apparire come il seguente comando:

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

Allo stesso modo il comando precedente uscirà con stato 0 se il "file-to-test" è testo (non binario).

Maggiori informazioni sui controlli -B e -T tramite il comando perldoc -f -X.

+0

http://perldoc.perl.org/functions/-X.html – Onlyjob

0

È una sorta di forza bruta per escludere i file binari con tr -d "[[:print:]\n\t]" < file | wc -c, ma non è nemmeno un'ipotesi euristica.

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 
' _ '{}' + 

Il seguente approccio a forza bruta utilizzando grep -a -m 1 $'[^[:print:]\t]' file sembra un po 'più veloce, però.

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 
' _ '{}' + 
1

Provare la seguente riga di comando:

file "$FILE" | grep -vq 'ASCII' && echo "$FILE is binary" 
+0

Bello ma viene ingannato dal file urt8 ascii. Ho usato: file "$ FILE" | grep -vq 'testo' –

6

Io uso

! grep -qI . $path 

unico svantaggio che vedo è che si prenderà in considerazione un file binario vuoto ma poi di nuovo, che decide se è sbagliato?

3

soluzione non ideale, ma semplice per verificare la presenza di un singolo file:

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

che controlla se il file in sostanza consiste carattere NUL.

Quindi, per leggere tutti i file non binari in modo ricorsivo utilizzando find utility è possibile fare:

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

O ancora più semplice utilizzando solo grep:

grep -rv "\x00" . 

Per soli cartella corrente, uso:

grep -v "\x00" * 
1

Decolla Bach's suggestion, penso --mime-encoding è la bandiera migliore per ottenere qualcosa di affidabile da file.

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

stamperà il file che file ritiene abbiano una codifica non binario. È possibile reindirizzare questa uscita tramite cut -d: -f1 per tagliare : encoding se si desidera solo il nome file.

Problemi correlati