¿Cómo puedo eliminar la extensión de un nombre de archivo en un script de Shell?

Resuelto mimicocotopus asked hace 12 años • 16 respuestas

¿Qué hay de malo con el siguiente código?

name='$filename | cut -f1 -d'.''

Tal como está, obtengo la cadena literal $filename | cut -f1 -d'.', pero si elimino las comillas no obtengo nada. Mientras tanto, escribiendo

"test.exe" | cut -f1 -d'.'

en un shell me da el resultado que quiero test. Ya sé que $filenamese le ha asignado el valor correcto. Lo que quiero hacer es asignar a una variable el nombre del archivo sin la extensión.

mimicocotopus avatar Aug 28 '12 11:08 mimicocotopus
Aceptado

También puede utilizar la expansión de parámetros:

$ filename=foo.txt
$ echo "${filename%.*}"
foo

Si tiene una ruta de archivo y no solo un nombre de archivo , querrá usarla basenameprimero para obtener solo el nombre del archivo, incluida la extensión. De lo contrario, si hay un punto sólo en el trazado (por ejemplo, path.to/myfileo ./myfile), se recortará dentro del trazado; incluso si no hay un punto en la ruta, obtendrá (por ejemplo, path/to/myfilesi la ruta es path/to/myfile.txt):

$ filepath=path.to/foo.txt
$ echo "${filepath%.*}"
path.to/foo
$ filename=$(basename $filepath)
$ echo $filename
foo.txt
$ echo "${filename%.*}"
foo

Sólo tenga en cuenta que si el nombre del archivo solo comienza con un punto (por ejemplo .bashrc), se eliminará todo el nombre del archivo.

chepner avatar Aug 28 '2012 04:08 chepner

Si conoce la extensión, puede usar el nombre base

$ basename /home/jsmith/base.wiki .wiki
base
Zombo avatar May 02 '2015 21:05 Zombo

Debería utilizar la sintaxis de sustitución de comandos$(command) cuando desee ejecutar un comando en un script/comando.

Entonces tu línea sería

name=$(echo "$filename" | cut -f 1 -d '.')

Explicación del código:

  1. echoobtener el valor de la variable $filenamey enviarlo a la salida estándar
  2. Luego tomamos la salida y la canalizamos al cutcomando
  3. cutUtilizará el . como delimitador (también conocido como separador) para cortar la cadena en segmentos y seleccionamos -fqué segmento queremos tener en la salida
  4. Entonces la $()sustitución del comando obtendrá el resultado y devolverá su valor.
  5. El valor devuelto se asignará a la variable denominadaname

Tenga en cuenta que esto da la porción de la variable hasta el primer período .:

$ filename=hello.world
$ echo "$filename" | cut -f 1 -d '.'
hello
$ filename=hello.hello.hello
$ echo "$filename" | cut -f 1 -d '.'
hello
$ filename=hello
$ echo "$filename" | cut -f 1 -d '.'
hello
Rohan avatar Aug 28 '2012 04:08 Rohan

Si su nombre de archivo contiene un punto (distinto al de la extensión), utilice esto:

echo $filename | rev | cut -f 2- -d '.' | rev
Manish Singh avatar Sep 15 '2015 11:09 Manish Singh

Utilizando únicamente el integrado de POSIX:

#!/usr/bin/env sh
path=this.path/with.dots/in.path.name/filename.tar.gz

# Get the basedir without external command
# by stripping out shortest trailing match of / followed by anything
dirname=${path%/*}

# Get the basename without external command
# by stripping out longest leading match of anything followed by /
basename=${path##*/}

# Strip uptmost trailing extension only
# by stripping out shortest trailing match of dot followed by anything
oneextless=${basename%.*}; echo "$oneextless" 

# Strip all extensions
# by stripping out longest trailing match of dot followed by anything
noext=${basename%%.*}; echo "$noext"

# Printout demo
printf %s\\n "$path" "$dirname" "$basename" "$oneextless" "$noext"

Demostración impresa:

this.path/with.dots/in.path.name/filename.tar.gz
this.path/with.dots/in.path.name
filename.tar.gz
filename.tar
filename
Léa Gris avatar Sep 19 '2020 15:09 Léa Gris