A las utilidades estándar de Unix les gusta grepy diffusan algunas heurísticas para clasificar archivos como "texto" o "binario". (Por ejemplo grep, la salida puede incluir líneas como Binary file frobozz matches.)
¿Existe una prueba conveniente que se pueda aplicar en un zshscript para realizar una clasificación similar de "texto / binario"? (Aparte de algo como grep '' somefile | grep -q Binary).
(Me doy cuenta de que cualquier prueba de este tipo sería necesariamente heurística y, por lo tanto, imperfecta).

filees una utilidad estándar y puede ejecutar la magia de archivos para determinar los tipos de archivos lo mejor que pueda. Puede indicar la mayoría de los formatos de texto y hace un trabajo bastante decente en formatos binarios. Si todo lo que intenta hacer es averiguar si un archivo es texto o no, ese es el comando que le interesa.filese imprimirán algunas versiones de , por ejemploshell script, para algunos archivos que me gustaría clasificar como "texto". ¿Hay alguna manerafilede imprimir solotextobinary?cutcomandos.filesalida de tuberíacutes la solución, claro, falta un espacio que lo hace fallar y eso ha hecho la mayoría de las personas allí abordan la Y en lugar de la X, pero los comentarios y respuestas de Stéphane muestran la forma correcta de determinar si el archivo es texto o no.Respuestas:
Si solicita
filesolo el tipo mime , obtendrá muchos diferentes, comotext/x-shellscript,application/x-executableetc., pero me imagino que si solo verifica la parte de "texto", obtendrá buenos resultados. Por ejemplo (-bpara ningún nombre de archivo en la salida):fuente
file, que es posible que pierda algunos formatos de texto:application/xml(y similar como RSS),application/ecmascript,application/json,image/svg+xml, ... Habría que la lista blanca aquellos.application/*tipos no están destinados al consumo humano, incluso cuando pueden estar basados en texto para facilitar el desarrollo y la depuración. Es por eso que hay tanto atext/xmlcomo aapplication/xml. Entonces, la pregunta de si considerarlos como texto depende de las necesidades del OP.cut -d/ -f1Otro enfoque sería usar
isutf8de la colección moreutils .Sale con 0 si el archivo es válido UTF-8 o ASCII, o cortocircuitos, imprime un mensaje de error (silencio con
-q) y sale con 1 de lo contrario.fuente
Si te gusta la heurística utilizada por GNU
grep, puedes usarla:Se busca NUL bytes en el primer tampón lee desde el archivo (unos kilo-bytes de un archivo normal, pero podría ser mucho menos por un tubo o de tubo o algunos dispositivos como
/dev/random). En las configuraciones regionales UTF-8, también marca las secuencias de bytes que no forman caracteres UTF-8 válidos. AsumeLC_ALLque no está configurado para algo donde el idioma no sea inglés.El
${1-$REPLY}formulario le permite usarlo comozshcalificador global:enumeraría los archivos binarios .
fuente
Puede intentar determinar si
iconvpuede leer el archivo. Esto tiene menos rendimiento quefile(que solo lee un par de bytes desde el principio), pero le dará resultados más confiables:Esto
iconvbásicamente hace que no funcione, pero si encuentra datos no válidos (UTF-8 no válido en este ejemplo), vomitará y saldrá.fuente
-fy en-tlugar de las opciones largas de GNU lo haría más portátil. Tenga en cuenta que llamará "binario" a los archivos que no puede abrir. Llamará a los archivos vacíos "texto".iconv. Pero-fy-tgeneralmente son mejores.Puede escribir un script que llame
filey usar una declaración de caso para verificar los casos que le interesan.Por ejemplo
aunque, por supuesto, puede haber muchos casos especiales que sean de interés. Solo comprobando
stringsuna copia delibmagic, veo unos 200 casos, por ejemplo,Algunos usan la cadena "texto" como parte de un tipo diferente, por ejemplo,
igualmente
scriptpodría ser parte de una palabra, pero no veo problemas en este caso. Pero una secuencia de comandos debe comprobar"text"como una palabra , no una subcadena .Como recordatorio, la
filesalida no utiliza una descripción precisa que siempre tenga "script" o "text". Los casos especiales son algo a considerar. Un seguimiento comentó que--mime-typefunciona mientras que este enfoque no lo haría, para los.svgarchivos. Sin embargo, en una prueba veo estos resultados para archivos svg:que seleccioné después de ver que mil archivos muestran solo 6 con "texto" en la salida de tipo mime. Podría decirse que hacer coincidir el "xml" al final de la salida de tipo mime podría ser más útil, por ejemplo, que hacer coincidir "SVG", pero usar un script para hacerlo lo lleva de vuelta a la sugerencia que se hace aquí.
El resultado de
filerequiere un poco de ajuste en cualquier escenario, y no es 100% confiable (varios de mis scripts de Perl lo confunden, llamándolos "datos").Hay más de una implementación de
file. El que se usa más comúnmente hace su trabajolibmagic, que puede usarse desde diferentes programas (quizás no directamente desdezsh, aunquepythonpuede).De acuerdo con la tabla de comparación de pruebas de archivos para shell, Perl, Ruby y Python , Perl tiene una
-Topción que puede usar para proporcionar esta información. Pero no enumera ninguna característica comparable parazsh.Otras lecturas:
fuente
file, la salida de GNU para archivos svg:SVG Scalable Vector Graphics imageno contiene la palabra texto. Pensé que este enfoque sería mejor que la respuesta aceptada de verificar el tipo MIME, pero aún falta algunos tipos.image/svg+xml. En realidad, solo verifiqué un archivo de 1000, solo 6 salieron como "texto" de acuerdo con el tipo mime solo. Seguiré con un script, que al menos se puede hacer que funcione según sea necesario.filetiene una opción--mime-encodingque intenta detectar la codificación de un archivo.Puede usar
file --mime-encoding | grep binarypara detectar si un archivo es un archivo binario. Funciona de manera confiable, aunque puede confundirse con un solo carácter no válido en un archivo de texto largo.Por ejemplo, alias
catal siguiente script de shell para evitar arruinar mi terminal al abrir inadvertidamente un archivo binario:fuente
Las categorías son arbitrarias. Antes de responder cómo hacer una clasificación, necesita una definición (estricta). Para tener una definición, necesitas un propósito .
Entonces, ¿qué quieres hacer con esa clasificación?
fuente
lo haré. Consulte la documentación para
-By-T(busque en esa página la cadenaThe -T and -B switches work as follows).fuente
perl -le 'print -B $ARGV[0] ? "binary" : "text"' --podría ser más claro O inclusoperl -le 'print -B $_ ? "binary" : "text", @ARGV > 1 ? "\t$_" : "" for @ARGV' --Contribuí a https://github.com/audreyr/binaryornot. Todavía no tiene un contenedor de línea de comandos, pero esta es una biblioteca simple de Python lo suficientemente fácil de llamar incluso desde la CLI. Utiliza una heurística bastante eficiente para determinar si un archivo es de texto o binario.
fuente
Ahora esta respuesta es un poco vieja, pero creo que mi amigo me enseñó un gran "truco" para hacer esto.
Utiliza el
diffcomando y comprueba tu archivo con un archivo de texto de prueba:$ diff filetocheck testfile.txtAhora si
filetocheckes un archivo binario, la salida sería:Binary files filetocheck and testfile.txt differDe esta manera, podría aprovechar el
diffcomando y, por ejemplo, escribir una función que verifique en un script.fuente