2012-03-21 15 views
8

Necesito crear una lista de todas las extensiones de archivos binarios ubicados dentro de un árbol de directorios.¿Cómo enumerar todas las extensiones de archivos binarios dentro de un árbol de directorios?

La pregunta principal debería ser cómo distinguir un archivo de texto de uno binario, y el resto debería ser pastel.

EDIT: ¿Esto es lo más cercano que tengo, alguna idea mejor?

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

¿Qué hay de archivo de texto codificación UTF-8? ¿Lo cuenta como un archivo binario? – PasteBT

+0

Por convención, los binarios ejecutables no tienen extensiones. – jordanm

+0

@jordanm Aparte de esa cosa de estrella, y estar en un color audaz. * pato * :) – Kaz

Respuesta

11

He aquí un truco para encontrar los archivos binarios:

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

El -m 1 hace grep no lee todo el archivo.

+2

Más limpio y más rápido que la solución que encontré, aquí está el último comando que utilicé 'grep -r -m 1"^"apps | grep"^Archivo binario "| sed -r 's:^Binary \ sfile \ s (. *) \ smatches: \ 1: g'' – dukeofgaming

+0

Un simple tubo para 'awk' {print $ 3} ''es más simple ... –

2

No hay diferencia entre un archivo binario y un archivo de texto en Linux. La utilidad file examina los contenidos y las conjeturas. Desafortunadamente, no es de mucha ayuda porque file no produce una respuesta simple de "binario o texto"; tiene un resultado complejo con una gran cantidad de casos que debería analizar.

Un enfoque es leer un prefijo de tamaño fijo de un archivo, digamos 256 bytes, y luego aplicar heurística. Por ejemplo, ¿están todos los valores de bytes de 0x0 a 0x7F, evitando los códigos de control a excepción de los espacios en blanco comunes? Eso sugiere ASCII? Si hay bytes 0x80 a 0xFF, ¿el decodificador completo (excepto un código al final que puede cortarse) decodifica como UTF-8 válido? Etc.

Una idea podría ser explotar astutamente las utilidades que detectan archivos binarios, como GNU diff.

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

Sin sustitución proceso, todavía funciona:

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

Ahora solo GrEP la salida de ese y buscar la palabra Binary.

La pregunta es si la heurística de diff para archivos binarios funciona para sus propósitos.

+2

Puede intentar usar 'file -i', lo que hace que muestre el formato de archivo como tipo MIME. Luego, puede verificar si el tipo mime tiene el prefijo 'text /'. Supongo que esto podría funcionar bastante bien. –

+0

¡Es bueno saberlo, gracias! Estaba mirando la página del hombre en busca de un espacio de salida más condensado de 'archivo 'pero no lo vi. – Kaz

1

No hay forma segura de diferenciar un archivo de "texto" de un archivo "binario", es trabajo de adivinar.

#!/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

Este perly de una sola línea que funcionó para mí, era también bastante rápido:

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

y es así como se pueden encontrar todos los archivos binarios de la carpeta actual:

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

-T es una prueba para archivos de texto, y -B para binario, y son opuestos el uno del otro *.

* perl file tests doc

0

Aquí es de una sola línea en Python para comprobar si el archivo es binario:

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

encontrar usando de forma recursiva con cáscara, véase el siguiente ejemplo:

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 {}" \; 

Para buscar todos los archivos no binarios, cambie && a ||.

0

Aquí es simple comando para listar todos los archivos binarios (que consisten NULL character) usando GNU grep:

grep -Palr '\x00' . 

Para imprimir la extensión de archivo más corto que 5 caracteres podemos utilizar awk y luego filtrar los duplicados mediante el uso de ya sea uniq o sort.

Así que todos juntos debería ser algo como:

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