¿Cuál es una forma efectiva de agregar automáticamente extensiones de archivo a archivos sin extensión?

¿Cuál es una forma efectiva de agregar automáticamente extensiones de archivo a archivos sin extensión?

Escribí un script bash hoy durante mi pausa para el almuerzo que busca archivos sin extensión en un directorio y les agrega una extensión de archivo.

El script es relativamente largo porque agregué un montón de indicadores y cosas como la selección de directorio y si copiar o sobrescribir el archivo, pero el meollo de su funcionalidad se puede replicar simplemente con esto:

#recursively find files in current directory that have no extension
for i in $(find . -type f ! -name "*.*"); do
    #guess that extension using file
    extfile=$(file --extension --brief $i)
    #select the first extension in the event file spits something weird (e.g. jpeg/jpe/jfif) 
    extawk=$(echo $extfile | awk -F/ '{print $1}')
    #copy the file to a file appended with the extension guessed from the former commands
    cp -av $i $i.$extawk
done

Es un poco más ordenado en mi script actual; solo quería dividir los comandos aquí para poder comentar por qué estaba haciendo las cosas.

Mi pregunta: Usar finden combinación con filela forma que he elegido probablemente no sea la forma más infalible de hacerlo: ¿cuál es elmejor¿Manera de adivinar y agregar extensiones de forma recursiva para un grupo masivo de diversos tipos de archivos entre varios directorios?

Respuesta1

for x in $(find …)falla connombres de archivos que contienen espacios en blanco (común) o caracteres comodín (algo poco común). Nunca analice la salida de find. Usar -exec.

Zsh'szmves conveniente para cambios de nombre masivos.

Construyamos un comando zmv que haga lo que usted quiere. Primero, construyamos el patrón de búsqueda:

autoload zmv
zmv -C -o -a -n -Q '(*/)#^*.*(.)' …
  • -Chace que los archivos se copien en lugar de moverse.
  • -o -apasa -aa cp.
  • -nsignifica no actuar, simplemente imprimir lo que se haría. Quítelo una vez que esté satisfecho. Sustitúyelo por -vsi quieres actuar pero también imprime lo que se está haciendo.
  • -Qpermiteclasificatorios globalesen el patrón.
  • (*/)#coincide con cero o más directorios. Utiliza el# operador global( extended_globsiempre está habilitado en zmv).
  • ^*.*utiliza el ^operador global para hacer coincidir archivos sin a .en su nombre.
  • (.)es un calificador global que restringe las coincidencias a archivos normales.
  • será reemplazado por el texto de reemplazo. Esto puede usarse $fpara referirse al nombre original.

zmvcalcula todos los nombres de reemplazo antes de realizar cualquier reemplazo y se quejará si ya existe algún nombre de reemplazo o si hay conflictos. Se omitirán los archivos cuyo nombre de reemplazo sea idéntico al original.

Ahora construyamos el texto de reemplazo. Usaremos muchoexpansión de parámetroscaracterísticas.

  1. Pregunta filepor la extensión:$(file --extension --brief -- $f)
  2. Anteponga a ., en preparación para el reemplazo: $(echo -n .; file --extension --brief -- $f)
    (Esto también se podría hacer con la expansión de parámetros: ${:-.$(…)}.)
  3. Si hay varias extensiones sugeridas (separadas por barras), conserve solo la primera:${$(echo -n .; file --extension --brief -- $f)%%/*}
  4. Si la extensión sugerida está vacía o ???, abandone (reemplace .o .???por una cadena vacía):${${$(echo -n .; file --extension --brief -- $f)%%/*}:#.(|\?\?\?)}
  5. Agregue la extensión agregada a $f(el nombre original). Si lo que estamos agregando está vacío, el archivo quedará intacto.

El comando resultante:

zmv -C -o -a -n -Q '(*/)#^*.*(.)' '$f${${$(echo -n .; file --extension --brief -- $f)%%/*}:#.(|\?\?\?)}'

Esto es un poco críptico y es posible que prefieras poner el código para generar el reemplazo en una función y uso zmv … '$(add_extension $f)'.

Respuesta2

Creo que la forma más efectiva es comparar los tipos mime del archivo con la base de datos ubicada en /usr/share/mime/globs.

  • globosen Linux sonextensión de archivo. Ejemplo dado, salida dearchivo globs
application/x-mswinurl:*.url
text/x-mrml:*.mrl
text/x-erlang:*.erl
audio/x-pn-audibleaudio:*.aa
application/x-bzip-compressed-tar:*.tbz2
application/x-netshow-channel:*.nsc
application/x-hdf:*.h4
application/pgp-keys:*.key
text/x-idl:*.idl
text/x-chdr:*.h
application/vnd.ms-powerpoint.presentation.macroEnabled.12:*.pptm
application/vnd.ms-powerpoint.presentation.macroEnabled.12:*.pptm
application/vnd.visio:*.vsd
application/x-hdf:*.h5
video/vnd.mpegurl:*.m4u
  • después de describir el tipo de ejemplo --> text/x-erlang, le dice a Linux que identifique todos los archivos *.comoerlangcon extensión .erl[glob], por eso -->*.erl
  • Puedes agregar tus propias extensiones para que se tengan en cuenta en el /etc/magicarchivo.

entonces ejecutando el comando:

mimetype -bM file
  • bArgumento para mostrarte type-app/extension(breve)

  • Margumento significamagiaes la forma en que Linux verifica el archivo en código de bytes, hexadecimal, binario para verificar que los archivos son realmente lo que dicen ser.

  • tipo de Mimicano devuelve /jpg/png/webpsolo devuelve un tipo, y es más corto quefile --mime-type file

Devoluciones:

image/webp

pensamientos finales

mimetypefunciona mejor conarchivos binarioscomo archivos PDF, imágenes y vídeos. Esto se debe a que puede verificar el binario, en cambio, text plaines solo eso, y necesitas identificarte con algo, y esto es más complicado, es por eso que los editores de texto pueden reconocer diferentes lenguajes de programación, necesita la ayuda del usuario y un lenguaje de servidor para cada lenguaje de programación.

para recursividad, creoárbolestá bien:

tree -FIi '*.*' | grep -v /$
  • El argumento Fes agregar /[barra] a los directorios, ejemplo, folderfolder/
  • El argumento Ies seleccionar el opuesto del patrón *.*[esto significa seleccionar todos los archivos con extensión], por lo que lo opuesto no es extensión
  • El argumento ies eliminar espacios de la salida del árbol.
  • grep -ves seleccionar revertir, es por eso que agrega el /argumento -F aárbolcomando al principio, para que pueda eliminar directorios y obtener solo archivos, con /$.

Mira más aquítipos de mimo

información relacionada