¿Cómo puedo saber si un archivo es binario (sin texto) en Python?
Estoy buscando en un gran conjunto de archivos en Python y sigo obteniendo coincidencias en archivos binarios. Esto hace que la salida se vea increíblemente desordenada.
Sé que podría usar grep -I
, pero estoy haciendo más con los datos de lo que permite grep.
En el pasado, solo hubiera buscado caracteres más grandes que 0x7f
, pero utf8
y similares, lo hacen imposible en los sistemas modernos. Idealmente, la solución sería rápida, pero cualquier solución servirá.
grep
sí misma utiliza para identificar archivos binarios es similar a la publicada por Jorge Orpinel a continuación . A menos que establezca la-z
opción, solo buscará un carácter nulo ("\000"
) en el archivo. Con-z
, busca"\200"
. Los interesados y / o escépticos pueden consultar la línea 1126 degrep.c
. Lo siento, no pude encontrar una página web con el código fuente, pero, por supuesto, puede obtenerlo en gnu.org o mediante una distribución .git diff
GNU comodiff
también utilizan la misma estrategia. No estoy seguro de si es tan frecuente porque es mucho más rápido y más fácil que la alternativa, o si es simplemente por la relativa rareza de los archivos UTF-16 en los sistemas que tienden a tener estas utilidades instaladas.Respuestas:
También puede utilizar el módulo Mimetypes :
Es bastante fácil compilar una lista de tipos de mime binarios. Por ejemplo, Apache se distribuye con un archivo mime.types que puede analizar en un conjunto de listas, binario y texto y luego verificar si el mime está en su lista de texto o binaria.
fuente
mimetypes
a usar el contenido de un archivo en lugar de solo su nombre?file
informa como "texto Unicode UTF-8, con líneas muy largas" pero mimetypes.gest_type () devolverá (None, None). Además, la lista de tipos MIME de Apache es una lista blanca / subconjunto. De ninguna manera es una lista completa de tipos mime. No se puede usar para clasificar todos los archivos como texto o no texto.Otro método más basado en el comportamiento del archivo (1) :
Ejemplo:
fuente
bytearray([7,8,9,10,12,13,27]) + bytearray(range(0x20, 0x7f)) + bytearray(range(0x80, 0x100))
lugar. Ver Python, archivo (1) - ¿Por qué se utilizan los números [7,8,9,10,12,13,27] y el rango (0x20, 0x100) para determinar texto frente a archivo binario y github.com/file/file/ blob /…0x7f
(DEL
).11
oVT
? En la tabla 11 se considera texto ASCII simple, y este es elvertical tab
.Si está utilizando python3 con utf-8, es sencillo, simplemente abra el archivo en modo texto y detenga el procesamiento si obtiene un archivo
UnicodeDecodeError
. Python3 usará unicode cuando maneje archivos en modo texto (y bytearray en modo binario) - si su codificación no puede decodificar archivos arbitrarios, es muy probable que lo obtengaUnicodeDecodeError
.Ejemplo:
fuente
with open(filename, 'r', encoding='utf-8') as f
directamente?Si ayuda, muchos tipos binarios comienzan con números mágicos. Aquí hay una lista de firmas de archivos.
fuente
Prueba esto:
fuente
git diff
realidad funciona de esta manera y , efectivamente , detecta archivos UTF-16 como binarios.diff
también funciona de esta manera. Tiene problemas similares con los archivos UTF-16.file
detecta correctamente los mismos archivos que el texto UTF-16. No he comprobadogrep
el código, pero también detecta archivos UTF-16 como binarios.file(1)
que no es seguro para imprimir sin conversión, por lo que este método es apropiado en este caso.Aquí hay una sugerencia que usa el comando de archivo Unix :
Uso de ejemplo:
Tiene las desventajas de no ser portátil para Windows (a menos que tenga algo como el
file
comando allí) y tener que generar un proceso externo para cada archivo, que puede no ser aceptable.fuente
file
como "Configuración congelada de Sendmail - versión m"; observe la ausencia de la cadena "texto". ¿Quizás usarfile -i
?Utilice la biblioteca binaryornot ( GitHub ).
Es muy simple y se basa en el código que se encuentra en esta pregunta de stackoverflow.
De hecho, puede escribir esto en 2 líneas de código, sin embargo, este paquete le evita tener que escribir y probar a fondo esas 2 líneas de código con todo tipo de tipos de archivos extraños, multiplataforma.
fuente
Normalmente tienes que adivinar.
Puede ver las extensiones como una pista, si los archivos las tienen.
También puede reconocer formatos binarios conocidos e ignorarlos.
De lo contrario, vea qué proporción de bytes ASCII no imprimibles tiene y adivine a partir de eso.
También puede intentar decodificar desde UTF-8 y ver si eso produce una salida sensible.
fuente
Una solución más corta, con una advertencia UTF-16:
fuente
for line in file
puede consumir una cantidad ilimitada de memoria hasta queb'\n'
se encuentre".read()"
devuelve aquí una cadena de bytes que es iterable (produce bytes individuales).Podemos usar Python para verificar si un archivo es binario, porque falla si intentamos abrir un archivo binario en modo texto.
fuente
Si no está en Windows, puede usar Python Magic para determinar el tipo de archivo. Luego puede verificar si es un tipo de texto / mímica.
fuente
Aquí hay una función que primero verifica si el archivo comienza con una lista de materiales y si no, busca un byte cero dentro de los 8192 bytes iniciales:
Técnicamente, la verificación de la lista de materiales de UTF-8 es innecesaria porque no debe contener cero bytes para fines prácticos. Pero como es una codificación muy común, es más rápido verificar la lista de materiales al principio en lugar de escanear todos los 8192 bytes en busca de 0.
fuente
Intente usar python-magic actualmente mantenido , que no es el mismo módulo en la respuesta de @Kami Kisiel. Esto es compatible con todas las plataformas, incluido Windows, sin embargo, necesitará los
libmagic
archivos binarios. Esto se explica en el archivo README.A diferencia del módulo mimetypes , no usa la extensión del archivo y en su lugar inspecciona el contenido del archivo.
fuente
Vine aquí buscando exactamente lo mismo: una solución integral proporcionada por la biblioteca estándar para detectar binarios o texto. Después de revisar las opciones sugeridas por la gente, el comando nix file parece ser la mejor opción (solo estoy desarrollando para linux boxen). Algunos otros publicaron soluciones usando archivos, pero son innecesariamente complicadas en mi opinión, así que esto es lo que se me ocurrió:
No hace falta decirlo, pero su código que llama a esta función debe asegurarse de que pueda leer un archivo antes de probarlo, de lo contrario, se detectará por error el archivo como binario.
fuente
Supongo que la mejor solución es usar la función guess_type. Contiene una lista con varios tipos MIME y también puede incluir sus propios tipos. Aquí viene el script que hice para solucionar mi problema:
Está dentro de una clase, como puede ver en base a la estructura de uso del código. Pero prácticamente puede cambiar las cosas que desea implementar dentro de su aplicación. Es bastante simple de usar. El método getTextFiles devuelve un objeto de lista con todos los archivos de texto que residen en el directorio que pasa en la variable de ruta.
fuente
en * NIX:
Si tiene acceso al
file
comando de shell, shlex puede ayudar a que el módulo de subproceso sea más utilizable:O también puede pegarlo en un bucle for para obtener la salida de todos los archivos en el directorio actual usando:
o para todos los subdirectorios:
fuente
La mayoría de los programas consideran que el archivo es binario (que es cualquier archivo que no esté "orientado a líneas") si contiene un carácter NULL .
Aquí está la versión de perl de
pp_fttext()
(pp_sys.c
) implementada en Python:Fuente: "Adivina si el archivo es de texto o binario" de Perl implementado en Python
fuente
estas en unix? si es así, intente:
Los valores de retorno del shell están invertidos (0 está bien, así que si encuentra "texto", devolverá un 0, y en Python esa es una expresión falsa).
fuente
file
con el-b
interruptor; imprimirá solo el tipo de archivo sin la ruta.is_binary_file = lambda filename: "text" in subprocess.check_output(["file", "-b", filename])
Una forma más sencilla es comprobar si el archivo consta de un carácter NULL (
\x00
) utilizando elin
operador, por ejemplo:Vea a continuación el ejemplo completo:
Uso de muestra:
fuente
Documentación
fuente