bash: ¿cómo se devuelven las extensiones de archivo?

Quiero escribir un script para devolver solo la extensión del nombre del archivo de entrada. Por ejemplo, textfile.txt debería devolver txt.

Soy nuevo en Linux y bash, y «m tratando de aprender a escribir guiones básicos. ¡Gracias!

Comentarios

  • Consulte también stackoverflow.com/questions/965053/…
  • ¿Cuál es la extensión del archivo linux-4.2.3.tar.xz que puede descargar desde kernel.org ? ¿Cuál es la extensión del archivo /bin/bash que sin duda está disponible en su sistema? Verá, el concepto de » extensión de archivo » es bastante extraño en Linux. La parte que sigue al punto tiene muy poca importancia para el sistema; es más bien una indicación para el usuario de lo que puede esperar de ese archivo. Y esa señal puede mentir o estar equivocada.

Responder

El shell, bash por ejemplo, tiene muchos características de manipulación de cadenas . Uno de ellos le permite eliminar todo hasta un patrón determinado:

${VAR##GLOB} 

La sintaxis anterior elimina todo de la variable $VAR hasta la primera coincidencia del glob GLOB. Entonces, para imprimir la extensión de un archivo sin su nombre, puede hacer:

$ file="file.txt" $ echo ${file##*.} txt 

Tenga en cuenta que esto también puede tratar con más de una «extensión»:

$ file="file.new.txt" $ echo ${file##*.} txt 

Si no quiere eso, use una # en su lugar, que eliminará la coincidencia más corta de los más largos:

$ echo ${file#*.} new.txt 

Ahora, para ejecutar esto en todos los archivos de un directorio, puede hacer:

$ ls file.avi file.pdf file.png file.txt $ for file in *; do echo "$file : ${file##*.}"; done file.avi : avi file.pdf : pdf file.png : png file.txt : txt 

Y, en aras de la integridad, también puede obtener el nombre del archivo sin su extensión usando ${file%.*}:

$ for file in *; do echo "$file : ${file##*.} : ${file%.*}"; done file.avi : avi : file file.pdf : pdf : file file.png : png : file file.txt : txt : file 

Comentarios

  • esto no ‘ t funciona para cosas como foo / .git / bar / baz Supongo que podrías hacer echo test.txt | awk -F ‘ / ‘ ‘ {print $ NF} ‘ | awk -F ‘. ‘ ‘ {print $ NF} ‘
  • @PaulM ¿qué quieres decir? Ese ‘ es un archivo sin extensión, ¿qué esperarías obtener de eso?
  • echo » / foo /var/.git/foo/bar.bz» | awk -F ‘ / ‘ ‘ {print $ NF} ‘ | awk -F ‘. ‘ ‘ {print $ NF} ‘ == > > bz
  • @PaulM file="/foo/var/.git/foo/bar.bz"; echo "${file##*.}": bz. No ‘ no veo ningún problema.

Responder

Con expansión de parámetros :

$ x="textfile.txt" $ echo ${x##*.} txt 

El ${parameter##word} elimina el prefijo más grande que coincide con word (todo excepto el final del archivo).

Respuesta

Un script bash muy simple que podría hacer lo que usted quisiera sería el siguiente:

#!/usr/bin/env bash echo "$1" | awk -F "." "{print $NF}" 

El script se invoca como script.sh test.txt, y lo que hace es

  • imprime $1 en stdout. $1 es el primer parámetro dado al script, en este caso test.txt.

  • la salida estándar de echo se canaliza a stdin para awk que divide la cadena (test.txt) en . y luego imprime el último elemento de la división (txt en este caso).

Solo un pequeño comentario, esto se puede hacer con una sola línea porque es una tarea bastante simple:

echo test.txt | awk -F "." "{print $NF}" 

Comentarios

  • Debe agregar comillas alrededor de $1, o corre el riesgo de romper los nombres de archivos que contienen espacios, etc.
  • esto no ‘ t funciona para cosas como foo / .git / bar / baz Supongo que podrías hacer echo test.txt | awk -F ‘ / ‘ ‘ {print $ NF} ‘ | awk -F ‘.’ ‘ {print $ NF} ‘

Responder

#!/bin/bash my_file=`basename "$1"` # get full file name as a script parameter and strip the path my_extension="${my_file##*.}" my_file="${my_file%.*}" # will return base file name before the extension echo "$my_file" echo "$my_extension" 

Ejecutar:

./script.sh index.html 

Salida:

index html 

Más información: Expansión de parámetros de shell | gnu.org

Respuesta

Para hacerlo, hay varias advertencias a tener en cuenta:

  • El archivo foo.d/bar no tiene extensión, no es un archivo foo con un .d/bar extensión.
  • También puede considerar que .bashrc no tiene extensión
  • El . y .. probablemente deberían tratarse de forma especial y se debería considerar que no tienen ninguna extensión.
  • ¿Para qué es la extensión? file.tar.gz? gz o tar.gz? ¿Qué pasa con holiday.picture.jpg o bash-4.4?
  • ¿Qué debe devolver para foo.d/? ¿Vacío o d?

Aquí, «haría:

#! /bin/sh - for file do case ${file##*/} in (?*.*) ext=${file##*.};; (*) ext=;; esac printf "%s\n" "$ext" done 

Comentarios

  • Excelente respuesta que maneja también las advertencias habituales y código útil especialmente como función.

Respuesta

Incluiré algunas opciones más en caso de que tenga sed o Perl instalado:

 #!/bin/bash ext=$(<<<"$1" sed -n "s/^[^.]*\.//p") printf "Extension: $ext\n" ext=$(<<<"$1" perl -ne "s/^.*?\.//&&print") printf "Extension: $ext\n" exit 0  
  • s/^[^.]*\.//p en sed y s/^.*?\.//&&print en perl: intente sustituir la secuencia más corta de caracteres que no sea . seguido de un carácter . al comienzo de la cadena; si se pudo realizar la sustitución, imprima el resultado de la sustitución;
 % bash script.sh file.bin Extension: bin Extension: bin  

Respuesta

Tenga cuidado. En Unix / Linux (y MacOS), la «extensión del nombre de archivo» es solo informativa (si es que tanto). Puede tener perfectamente un script en Perl llamado photo.gif, o un archivo GIF llamado poem.txt. O incluso un archivo llamado some.txt.png.

Comentarios

  • Es ‘ es tan informativo en MS Windows, ‘ es solo que allí el programa de shell predeterminado hace suposiciones más sólidas sobre el emparejamiento de extensión – contenido, y debería haber un desajuste entre el nombre y el contenido, todo el asunto generalmente comienza a gritar errores, lo pobre.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *