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

¿Qué pasa con el siguiente código?

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

Como es, obtengo la cadena literal $filename | cut -f1 -d'.' $filename | cut -f1 -d'.' , pero si elimino las citas, no obtengo nada. Mientras tanto, escribiendo

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

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

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

Entonces tu línea sería

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

Explicación del código:

  1. echo obtiene el valor de la variable $filename y lo envía a la salida estándar
  2. A continuación, tomamos la salida y la canalizamos al comando de cut
  3. El cut usará el. como delimitador (también conocido como separador) para cortar la cuerda en segmentos y por -f seleccionamos qué segmento queremos tener en la salida
  4. Entonces la sustitución del comando $() obtendrá la salida y devolverá su valor
  5. El valor devuelto se asignará a la variable llamada name

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 

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

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

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

 $ basename /home/jsmith/base.wiki .wiki base 

Si su nombre de archivo contiene un punto (que no sea el de la extensión), utilice esto:

 echo $filename | rev | cut -f 2- -d '.' | rev 
 file1=/tmp/main.one.two.sh t=$(basename "$file1") # output is main.one.two.sh name=$(echo "$file1" | sed -e 's/\.[^.]*$//') # output is /tmp/main.one.two name=$(echo "$t" | sed -e 's/\.[^.]*$//') # output is main.one.two 

usa lo que quieras Aquí asumo eso último . (punto) seguido de texto es extensión.

Como señala Hawker65 en el comentario de la respuesta de chepner, la solución más votada no se ocupa de múltiples extensiones (como filename.tar.gz), ni de puntos en el rest de la ruta (como this.path / with .dots / in.path.name). Una posible solución es:

 a=this.path/with.dots/in.path.name/filename.tar.gz echo $(dirname $a)/$(basename $a | cut -d. -f1) 

Dos problemas con tu código:

  1. Usó un ‘(tick) en lugar de un `(back tick) para rodear los comandos que generan la cadena que desea almacenar en la variable.
  2. No hizo “eco” de la variable “$ filename” al conducto en el comando “cortar”.

Cambiaría tu código a “name =` echo $ filename | cut -f 1 -d ‘.’ `”, como se muestra a continuación (de nuevo, observe las marcas de retroceso que rodean la definición de variable de nombre):

 $> filename=foo.txt $> echo $filename foo.txt $> name=`echo $filename | cut -f1 -d'.'` $> echo $name foo $> 
 #!/bin/bash filename=program.c name=$(basename "$filename" .c) echo "$name" 

productos:

 program 
 #!/bin/bash file=/tmp/foo.bar.gz echo $file ${file%.*} 

productos:

 /tmp/foo.bar.gz /tmp/foo.bar 

Tenga en cuenta que solo se elimina la última extensión.