2012-03-21 12 views
8

Ho bisogno di creare un elenco di tutte le estensioni di file binari che si trovano all'interno di un albero di directory.Come elencare tutte le estensioni di file binari all'interno di un albero di directory?

La domanda principale dovrebbe essere come distinguere un file di testo da uno binario, e il resto dovrebbe essere una torta.

EDIT: questo è il più vicino che ho, qualche idea migliore?

find . -type f|xargs file|grep -v text|sed -r 's:.*\.(.*)\:.*:\1:g' 
+0

Come su file di testo codifica UTF-8? Conta come un file binario? – PasteBT

+0

Per convenzione, i file binari eseguibili non hanno estensioni. – jordanm

+0

@jordanm Oltre a quella cosa stellare, e in un colore audace. * duck * :) – Kaz

risposta

11

Ecco un trucco per trovare i file binari:

grep -r -m 1 "^" <Your Root> | grep "^Binary file" 

Il -m 1 fa grep non legge tutti i file.

+2

Più pulito e più veloce della soluzione che ho trovato, ecco l'ultimo comando che ho usato 'grep -r -m 1"^"apps | grep"^File binario "| sed -r ':^Binary \ sfile \ s (. *) \ smatches: \ 1: g'' – dukeofgaming

+0

Un semplice pipe per 'awk '{print $ 3}'' è più semplice ... –

2

Non c'è differenza tra un file binario e un file di testo su Linux. L'utilità file esamina i contenuti e le ipotesi. Sfortunatamente, non è di grande aiuto perché file non produce una semplice risposta "binaria o di testo"; ha un output complesso con un numero elevato di casi che dovresti analizzare.

Un approccio consiste nel leggere alcuni prefissi di dimensioni fisse di un file, ad esempio 256 byte, e quindi applicare delle euristiche. Ad esempio, sono tutti i valori di byte da 0x0 a 0x7F, evitando i codici di controllo ad eccezione degli spazi bianchi comuni? Questo suggerisce ASCII? Se ci sono byte da 0x80 a 0xFF, l'intero buffer (ad eccezione di un codice alla fine che può essere troncato) decodifica come UTF-8 valido? Etc.

Un'idea potrebbe essere quella di sfruttare di nascosto le utilità che rilevano file binari, come GNU diff.

$ diff -r /bin/ls <(echo foo) 
Binary files /bin/ls and /dev/fd/63 differ 

Senza sostituzione di processo, funziona ancora:

$ diff -r /bin/ls /dev/null 
Binary files /bin/ls and /dev/null differ 

Ora basta grep l'output di questo e cercare la parola Binary.

La domanda è se l'euristica diff per i file binari funziona per i propri scopi.

+2

Puoi provare a usare 'file -i', che fa sì che emetta il formato di file come tipo MIME. Quindi, puoi controllare se il tipo mime ha il prefisso 'text /'. Immagino che questo potrebbe funzionare abbastanza bene. –

+0

Buono a sapersi, grazie! Stavo dando un'occhiata alla pagina man in cerca di uno spazio di output più condensato da 'file', ma non l'ho notato. – Kaz

1

Non esiste un modo sicuro per differenziare un file di "testo" da un file "binario", è probabile che si lavori.

#!/bin/bash 
guess=`echo \`head -c 4096 $1 | strings -a -n 1 | wc -c \` '* 1.05 /' \`head -c 4096 $1 | wc -c \` | bc `; 
if [ $guess -eq 1 ] ; then 
    echo $1 "is text file" 
    exit 0 
else 
    echo $1 "is binary file" 
    exit 1 
fi 
4

Questo Perly one-liner ha lavorato per me, è stato anche abbastanza veloce:

find . -type f -exec perl -MFile::Basename -e 'print (-T $_ ? "" : (fileparse ($_, qr/\.[^.]*/))[2] . "\n") for @ARGV' {} + | sort | uniq 

e in questo modo si possono trovare tutti i file binari nella cartella corrente:

find . -type f -exec perl -e 'print (-B $_ ? "$_\n" : "") for @ARGV' {} + 

-T è un test per i file di testo, e -B per il binario, e sono opposti l'uno dell'altro *.

* perl file tests doc

0

Ecco uno-liner in Python per verificare se il file è binario:

b"\x00" in open("/etc/hosts", "rb").read() 

Trova usarlo in modo ricorsivo in guscio, vedere l'esempio di seguito:

IS_BINARY='import sys; sys.exit(not b"\x00" in open(sys.argv[1], "rb").read())' 
find . -type f -exec bash -c "python -c '$IS_BINARY' {} && echo {}" \; 

Per trovare tutti i file non binari, modificare && in ||.

0

Ecco semplice comando alla lista di tutti i file binari (che consistono NULL character) che utilizzano GNU grep:

grep -Palr '\x00' . 

Per stampare l'estensione del file più breve di 5 caratteri che possiamo usare awk e poi filtrare i duplicati utilizzando uniq o sort.

Quindi tutti insieme dovrebbe essere qualcosa di simile:

grep -Palr '\x00' . | awk -F. '{if (length($NF) < 5) print $NF}' | sort -u 
Problemi correlati