2012-09-29 22 views
5

estoy tomando un curso de introducción a UNIX y tiene una pregunta tarea que sigue:¿Cómo contar todos los archivos legibles en Bash?

¿Cuántos archivos en la pregunta anterior son archivos de texto? Un archivo de texto es cualquier archivo que contenga contenido legible por humanos. (PREGUNTA DE TRUCO. Ejecute el comando de archivo en un archivo para ver si el archivo es de texto o binario. Si simplemente cuenta el número de archivos con la extensión .txt, no obtendrá puntos para esta pregunta)

La pregunta anterior simplemente preguntaba cuántos archivos regulares había, lo cual era fácil de averiguar haciendo find . -type f | wc -l.

Solo estoy teniendo problemas para determinar qué es el "contenido legible por humanos", ya que supongo que significa algo además de binario/ensamblado, pero pensé que eso es lo que muestra -type f. ¿Tal vez eso es lo que quiso decir el profesor al decir "pregunta engañosa"?

Esta pregunta tiene un seguimiento posterior que también pregunta "¿Qué archivos de texto contienen la cadena" csc "en cualquier combinación de mayúsculas y minúsculas?". Obviamente, "texto" se refiere a mucho más que a los archivos .txt, ¡pero tengo que resolver la primera pregunta para determinarlo!

+1

No, 'find -type F' excluye directorios, ficheros de dispositivos, etc. ("especulación archivos ial "), es decir, objetos del sistema de archivos que no sean puros. No examina el contenido de los archivos en absoluto, solo la información de tipo en la entrada del directorio (inode). Unix no hace ninguna distinción entre archivos "binarios" y "texto" (y para este cabezal Unix, cualquier intento de definir dicha distinción entra en una pendiente resbaladiza). – tripleee

Respuesta

6

Cotizaciones añadido para mayor claridad:

ejecutar el "archivo" de comandos en un archivo para ver si el archivo es un archivo de texto o un archivo de datos binarios!

El comando file inspeccionará los archivos y le indicará qué tipo de archivo parecen ser. La palabra "texto" estará (casi) siempre en la descripción de los archivos de texto.

Por ejemplo:

desktop.ini: Little-endian UTF-16 Unicode text, with CRLF, CR line terminators 
tw2-wasteland.jpg: JPEG image data, JFIF standard 1.02 

Así que la primera parte le pide que ejecute el comando file y analizar su producción.

Estoy teniendo problemas para determinar qué es el "contenido legible para los humanos", ya que supongo que significa algo más que binario/ensamblado, pero pensé que eso es lo que muestra el tipo f.

find -type f encuentra los archivos. Filtra otros objetos del sistema de archivos como directorios, enlaces simbólicos y conectores. Sin embargo, coincidirá con cualquier tipo de archivo: archivos binarios, archivos de texto, cualquier cosa.

Tal vez eso es lo que el profesor quiso decir con "pregunta trucada"?

Parece que solo dice que no haga find -name '*.txt' o algún otro comando para buscar archivos de texto. No asuma una extensión de archivo en particular. Las extensiones de archivo tienen mucho menos significado en UNIX que en Windows. ¡Muchos archivos ni siquiera tienen extensiones de archivos!


Estoy pensando que el profesor quiere que seamos capaces de ejecutar el comando de archivo en todos los archivos y contar el número de los que tienen 'texto' en ella.

¿Qué tal una respuesta de varias partes? Le daré la solución directa en el # 1, que es probablemente lo que su profesor está buscando. Y si está interesado le explicaré sus deficiencias y cómo puede mejorarlo.

  1. Una forma es utilizar xargs, si es que ha aprendido sobre eso. xargs ejecuta otro comando, usando los datos de stdin como argumentos de ese comando.

    $ find . -type f | xargs file 
    ./netbeans-6.7.1.desktop: ASCII text 
    ./VMWare.desktop:   a /usr/bin/env xdg-open script text executable 
    ./VMWare:     cannot open `./VMWare' (No such file or directory) 
    (copy).desktop:   cannot open `(copy).desktop' (No such file or directory) 
    ./Eclipse.desktop:  a /usr/bin/env xdg-open script text executable 
    
  2. Eso funciona. Más o menos Sería lo suficientemente bueno para una tarea de tarea. Pero no es lo suficientemente bueno para un guión del mundo real.

    Observe cómo se rompió en el archivo VMWare (copy).desktop porque tiene un espacio en él. Esto se debe al comportamiento predeterminado de xargs de dividir los argumentos en espacios en blanco. Podemos arreglar eso usando xargs -0 para dividir los argumentos de comando en los caracteres NUL en lugar de los espacios en blanco. Los nombres de archivos no pueden contener caracteres NUL, por lo que podrán manejar cualquier cosa.

    $ find . -type f -print0 | xargs -0 file 
    ./netbeans-6.7.1.desktop: ASCII text 
    ./VMWare.desktop:   a /usr/bin/env xdg-open script text executable 
    ./VMWare (copy).desktop: a /usr/bin/env xdg-open script text executable 
    ./Eclipse.desktop:  a /usr/bin/env xdg-open script text executable 
    
  3. Esto es lo suficientemente bueno para un guión de producción, y es algo que vas a encontrar un montón. Pero personalmente prefiero una sintaxis alternativa que no requiera una tubería, y por eso es un poco más eficiente.

    $ find . -type f -exec file {} \; 
    ./netbeans-6.7.1.desktop: ASCII text 
    ./VMWare.desktop:   a /usr/bin/env xdg-open script text executable 
    ./VMWare (copy).desktop: a /usr/bin/env xdg-open script text executable 
    ./Eclipse.desktop:  a /usr/bin/env xdg-open script text executable 
    

    a entender que -exec, las llamadas file en repetidas ocasiones, en sustitución de {} con cada nombre de archivo que encuentra. El punto y coma \; marca el final del comando file.

+0

Seguramente "legible por humanos" es una función del ser humano y no del archivo. Siempre he tenido la fuerte impresión de que la mayoría de los humanos no pueden leer la mayoría de los archivos llamados README, por ejemplo. – rici

+0

Gracias por la ayuda chicos, sé que el archivo puede determinar si un archivo es o no un archivo de texto, pero olvidé mencionar que el resultado final de la primera pregunta sobre encontrar archivos regulares resultó en 153 archivos (es un directorio lleno de subdirectorios con los que estamos trabajando), así que estoy pensando que el profesor quiere que podamos ejecutar el comando de archivo en todos los archivos y contar el número de ellos con 'texto' en él.¿Cómo voy a hacer eso, suponiendo que sea posible? – Rekson

+0

@ user1687406 Actualicé mi respuesta con una explicación (excesivamente) detallada sobre la combinación de 'buscar' y' archivo'. No entré en cómo 'grep' la salida. Avíseme si desea ayuda con eso. –

0

hay una manera agradable y fácil de determinar si un archivo es un archivo de texto legible por humanos, sólo tiene que utilizar file --mime-type <filename> y buscar 'text/plain'. Se trabajará sin importar si el archivo tiene un final o tiene un final diferente a .txt

Así que haría algo como:

FILES=`find $YOUR_DIR -type f` 

for file in $FILES ; 
do 

mime=`/usr/bin/file --mime-type $YOUR_DIR/$file | /bin/sed 's/^.* //'` 

if [ $mime = "text/plain" ]; then  
    fileTotal=$((fileTotal + 1)) 
    echo "$fileTotal - $file" 
fi 

done 

echo "$fileTotal human readable files found!" 

y la salida sería como algo:

1 - /sampledir/samplefile 
2 - /sampledir/anothersamplefile 
.... 
23 human readable files found! 

Si quieres ir más lejos a más tipos MIME que son legibles (por ejemplo, hace HTML y/o XML cuentan?) echar un vistazo a http://www.feedforall.com/mime-types.htm

Cuestiones relacionadas