¿Es posible usar el findcomando para encontrar todos los archivos "no binarios" en un directorio? Aquí está el problema que estoy tratando de resolver.
Recibí un archivo de archivos de un usuario de Windows. Este archivo contiene código fuente y archivos de imagen. Nuestro sistema de compilación no funciona bien con archivos que tienen terminaciones de línea de Windows. Tengo un programa de línea de comandos ( flip -u) que cambiará las terminaciones de línea entre * nix y windows. Entonces, me gustaría hacer algo como esto
find . -type f | xargs flip -u
Sin embargo, si este comando se ejecuta contra un archivo de imagen u otro archivo multimedia binario, dañará el archivo. Me doy cuenta de que podría crear una lista de extensiones de archivo y filtrar con eso, pero prefiero tener algo que no dependa de que mantenga esa lista actualizada.
Entonces, ¿hay alguna manera de encontrar todos los archivos no binarios en un árbol de directorios? ¿O hay una solución alternativa que debería considerar?

fileutilidad en algún lugar de su secuencia de comandos / canalización para identificar si el archivo es de datos o textoRespuestas:
Usaría
filey canalizaría la salida en grep o awk para encontrar archivos de texto, luego extraería solo la parte del nombre del archivo defilela salida y la canalizaría en xargs.algo como:
Tenga en cuenta que el grep busca 'texto ASCII' en lugar de cualquier 'texto'; probablemente no quiera meterse con documentos de texto enriquecido o archivos de texto unicode, etc.
También puede usar
find(o lo que sea) para generar una lista de archivos para examinar confile:El
-d'\n'argumento de xargs hace que xargs trate cada línea de entrada como un argumento separado, atendiendo así a los nombres de archivos con espacios y otros caracteres problemáticos. es decir, es una alternativa axargs -0cuando la fuente de entrada no genera o no puede generar una salida separada por NULL (comofindla-print0opción de '). De acuerdo con el registro de cambios, xargs obtuvo la opción-d/--delimiteren septiembre de 2005, por lo que debería estar en cualquier distribución de Linux no antigua (no estaba seguro, por eso lo verifiqué, solo recordaba vagamente que era una adición "reciente").Tenga en cuenta que un salto de línea es un carácter válido en los nombres de archivo, por lo que se interrumpirá si algún nombre de archivo tiene un salto de línea. Para los usuarios típicos de Unix, esto es patológicamente loco, pero no se desconoce si los archivos se originaron en máquinas Mac o Windows.
También tenga en cuenta que
fileno es perfecto. Es muy bueno para detectar el tipo de datos en un archivo, pero en ocasiones puede confundirse.He usado numerosas variaciones de este método muchas veces en el pasado con éxito.
fuente
filemuestra enEnglish textlugar deASCII texten mi sistema Solaris, por lo que modifiqué esa parte en consecuencia. Además, lo reemplacéawk -F: '{print $1}'con el equivalentecut -f1 -d:.grep -Ifiltros binariostextdebería ser suficiente. Esto también recogeráfiledescripciones comoASCII Java program textoHTML document textotroff or preprocessor input text.ASCII textevitar estropear los RTF.No. No hay nada especial en un archivo binario o no binario. Puede usar heurísticas como 'contiene solo caracteres en 0x01–0x7F', pero eso llamará archivos de texto con archivos binarios de caracteres no ASCII y archivos de texto de archivos binarios desafortunados.
Ahora, una vez que has ignorado eso ...
archivos zip
Si proviene de su usuario de Windows como un archivo zip, el formato zip admite marcar archivos como binarios o texto en el propio archivo. Puede usar la
-aopción de descomprimir para prestar atención a esto y convertir. Por supuesto, vea el primer párrafo sobre por qué esto puede no ser una buena idea (el programa zip puede haber adivinado mal cuando creó el archivo).zipinfo le dirá qué archivos son binarios (b) o de texto (t) en su lista de archivos zip.
otros archivos
El comando de archivo mirará un archivo e intentará identificarlo. En particular, probablemente encontrará
-iútil su opción (tipo MIME de salida); solo convierte archivos con texto de tipo / *fuente
Una solución general para procesar solo archivos no binarios al
bashusarfile -b --mime-encoding:Me puse en contacto con el autor de la utilidad de archivo y agregó un ingenioso
-00parámetro en la versión 5.26 (lanzada el 16/04/2016, por ejemplo, en Arch y Ubuntu 16.10 actual) que imprimefile\0result\0para múltiples archivos alimentados a la vez, de esta manera puede hacerlo p.ej:(La
awkparte es filtrar cada archivo que no es no binario.ORSEs el separador de salida).También se puede usar en un bucle, por supuesto:
Basado en esto y en lo anterior, creé un pequeño
bashscript para filtrar archivos binarios que utiliza el nuevo método usando el-00parámetro defileen versiones más nuevas y vuelve al método anterior en versiones anteriores:O aquí uno más POSIX-y, pero requiere soporte para
sort -V:fuente
La respuesta aceptada no los encontró todos para mí. Aquí hay un ejemplo usando grep's
-Ipara ignorar binarios e ignorando todos los archivos ocultos ...Aquí está en uso en una aplicación práctica: dos2unix
https://unix.stackexchange.com/a/365679/112190
fuente
La respuesta de Cas es buena, pero supone nombres de archivo sanos ; en particular se supone que los nombres de archivo no contendrán nuevas líneas.
No hay una buena razón para hacer esta suposición aquí, ya que es bastante simple (y en realidad más limpio en mi opinión) manejar ese caso correctamente también:
El
findcomando solo utiliza funciones especificadas por POSIX . El uso-execpara ejecutar comandos arbitrarios como pruebas booleanas es simple, robusto (maneja nombres de archivo impares correctamente) y más portátil que-print0.De hecho, POSIX especifica todas las partes del comando, excepto
flip.Tenga en cuenta que
fileno garantiza la precisión de los resultados que devuelve. Sin embargo, en la práctica, el grepping para "texto ASCII" en su salida es bastante confiable.(Es posible que falten algunos archivos de texto, pero es muy poco probable que identifique incorrectamente un archivo binario como "texto ASCII" y lo destruya, por lo que estamos equivocados).
fuente
callspuede ser bastante lento, por ejemplo, para videos le dirá todo sobre la codificación.-.file, puede tomar varios archivos como argumentos.findcomando prefijará./a cualquier nombre de archivo pasado al comando de shell; (3) Usargrepcomo prueba en unafilesalida de comando único a la vez es la única forma POSIX que puedo ver para garantizar el manejo correcto de los nombres de archivo que pueden contener nuevas líneas.filecompatible con la--mime-encodingbandera y el--separador, ninguno de los cuales está garantizado por POSIX .Esto encontrará todos los archivos regulares (
-type f) en el directorio actual (o inferior) quegreppiensa que no están vacíos ni son binarios.Se utiliza
grep -Ipara distinguir entre archivos binarios y no binarios. La-Imarca y harágrepque salga con un estado de salida distinto de cero cuando detecte que un archivo es binario. Un archivo "binario" es, de acuerdo congrep, un archivo que contiene caracteres fuera del rango ASCII imprimible.La
-qopción degrephará que se cierre con un estado de salida cero si se encuentra el patrón dado, sin emitir ningún dato. El patrón que usamos es un solo punto, que coincidirá con cualquier carácter.Si se encuentra que el archivo no es binario y contiene al menos un carácter, se imprime el nombre del archivo.
Si te sientes valiente, también puedes enchufarlo
flip -u:fuente
Prueba esto :
Donde el argumento de
grep '[^ -~]'es'[^<tab><space>-~]'.Si lo escribe en una línea de comando de shell, escriba Ctrl+ Vantes Tab. En un editor, no debería haber ningún problema.
'[^<tab><space>-~]'coincidirá con cualquier carácter que no sea texto ASCII (los retornos de carro se ignorangrep).-Limprimirá solo el nombre de archivo de los archivos que no coinciden-Zgenerará nombres de archivo separados con un carácter nulo (paraxargs -0)fuente
grep -P(si está disponible)\testá disponible. Alternativamente, usando la traducción local si el shell lo admite:$'\t'(bashyzshhacer).Solución alternativa:
El comando dos2unix convertirá los finales de línea de Windows CRLF a Unix LF y omitirá automáticamente los archivos binarios. Lo aplico recursivamente usando:
fuente
dos2unixpuede tomar varios nombres de archivo como argumento, es mucho más eficiente hacerlofind . -type f -exec dos2unix {} +sudo find / (-type f -and -path '* / git / *' -iname 'README') -exec grep -liI '100644 \ | 100755' {} \; -exec flip -u {} \;
i. (-type f -and -path '* / git / *' -iname 'README'): busca archivos dentro de una ruta que contenga el nombre git y el archivo con el nombre README. Si conoce alguna carpeta y nombre de archivo específicos para buscar, será útil.
El comando ii.-exec ejecuta un comando en el nombre del archivo generado por find
iii. \; indica el fin del comando
iv. {} es el resultado del archivo / nombre de carpeta encontrado en la búsqueda de búsqueda anterior
v. Se pueden ejecutar varios comandos posteriormente. Al agregar -exec "comando" \; como con -exec flip -u \;
vii.grep
puede clonar este directorio de prueba y probarlo: https://github.com/alphaCTzo7G/stackexchange/tree/master/linux/findSolution204092017
respuesta más detallada aquí: https://github.com/alphaCTzo7G/stackexchange/blob/master/linux/findSolution204092017/README.md
fuente