¿Cómo puedo obtener la(s) extensión(es) de un archivo según su contenido?

¿Cómo puedo obtener la(s) extensión(es) de un archivo según su contenido?

Estoy planeando descargar un montón de imágenes de un sitio web que no vienen con una extensión, por lo que quiero agregar una según el contenido del archivo o el tipo mime.

file <filename>hace un gran trabajo identificando el tipo de archivo, sin embargo necesito la extensión.

--extension
      Print a slash-separated list of valid extensions for the file type found.

Esto es de filela página de manual, pero no parece funcionar:

$ file --extension test_text_file.txt
test_text_file.txt: ???

$ file --extension test_png_file.png
test_png_file.png: ???

$ file --extension test_gif_file.gif
test_gif_file.gif: ???

Literalmente imprime ???cada archivo que le paso, incluso aquellos que ya tienen una extensión adecuada. Todos estos son archivos válidos de su tipo y son reconocidos perfectamente filesin ellos --extension.

¿Por qué file --extensionno me funciona y qué puedo usar para obtener la extensión de un archivo?

Una idea sería usar file --mime-typey luego crear una matriz de tabla de despacho que asigne tipos mime conocidos a sus extensiones, pero prefiero tener una solución más simple y segura.

Respuesta1

¿Por qué file --extensionno me funciona?

No sólo para ti. Veresta pregunta. Uno de los comentarios allí parece correcto:

¿Quizás solo una característica muy, muy incompleta?

No he encontrado ninguna herramienta Unix estándar para realizar la conversión, por lo que su idea puede ser la solución más sencilla de todos modos.

Una idea sería usar file --mime-typey luego crear una matriz de tabla de despacho que asigne tipos mime conocidos a sus extensiones, pero prefiero tener una solución más simple y segura.

Tenga en cuenta que existe un mapa de este tipo, es /etc/mime.types. Veresta otra pregunta sobre Unix y Linux SE. Basado en una de las respuestas, se me ocurrió la siguiente función:

function getext() {
   [ "$#" != 1 ] && { echo "Wrong number of arguments. Provide exactly one." >&2; return 254; }
   [ -r "$1" ] || { echo "Not a file, nonexistent or unreadable." >&2; return 1; }
   grep "^$(file -b --mime-type "$1")"$'\t' /etc/mime.types |
      awk -F '\t+' '{print $2}'
}

Uso:

getext test_text_file.txt   # it takes just one argument

Adáptelo a sus necesidades, conviértalo en un script, etc. Las principales preocupaciones:

  • Si tiene éxito (estado de salida 0), la salida puede no estar vacía o estar vacía (ni siquiera \n).
  • Algunos tipos mime devuelven más de una extensión. Puedes usarlo cut -d ' ' -f 1para obtener como máximo uno, aunque puede que no sea el que deseas.
  • Por lo tanto, un archivo de mapa personalizado en lugar de /etc/mime.typespuede resultar útil. Este comando le mostrará qué tipos MIME existen en el directorio actual (y subdirectorios):

    find . -type f -exec file -b --mime-type {} + | sort | uniq
    
  • grepno debería coincidir más de una vez (al menos con /etc/mime.types); ^(inicio de línea) y $'\t'(tabulación) están ahí para evitar coincidencias parciales. Utilice grep -m 1 ...(o head -n 1posterior) para asegurarse de obtener como máximo una línea.

Respuesta2

Creo que vale la pena mencionar que muestra la extensión para algunos tipos de archivos.

file --preserve-date --special-files --extension *

Resultado:

BMP_file:          ???
CPP_file:          ???
FIFO_file:         ERROR: (null)
GZ_file:           ???
HAR_file:          ???
H_file:            ???
HTML_file:         ???
JAR_file:          zip/cbz
JAVA_CLASS_file:   ???
JAVA_JAVA_file:    ???
JPG_file:          jpeg/jpg/jpe/jfif
MKV_file:          ???
MP3_file:          ???
MP4_file:          ???
ODT_file:          ???
PDF_file:          ???
PNG_file:          ???
PPS_file:          ???
SHELL_SCRIPT_file: ???
SO_file:           ???
TIFF_file:         ???
TMP_file_GBQcW:    ???
XML_file:          ???
ZIP_file:          zip/cbz

información relacionada