¿Cómo elimino el sufijo del archivo y la porción de ruta de una cadena de ruta en Bash?

Dada una ruta de archivo de cadena como “/foo/fizzbuzz.bar”, ¿cómo usaría bash para extraer solo la parte “fizzbuzz” de dicha cadena?

Aquí se explica cómo hacerlo con los operadores # y% en Bash.

$ x="/foo/fizzbuzz.bar" $ y=${x%.bar} $ echo ${y##*/} fizzbuzz 

${x%.bar} también podría ser ${x%.*} para eliminar todo después de un punto o ${x%%.*} para eliminar todo después del primer punto.

Ejemplo:

 $ x="/foo/fizzbuzz.bar.quux" $ y=${x%.*} $ echo $y /foo/fizzbuzz.bar $ y=${x%%.*} $ echo $y /foo/fizzbuzz 

La documentación se puede encontrar en el manual de Bash . Busque la sección de coincidencia de la parte final de ${parameter%word} y ${parameter%%word} .

mira el comando basename:

 NAME=`basename /foo/fizzbuzz.bar .bar` 

Pure bash, hecho en dos operaciones separadas:

  1. Elimine la ruta de una cadena de ruta:

     path=/foo/bar/bim/baz/file.gif file=${path##*/} #$file is now 'file.gif' 
  2. Elimine la extensión de una cadena de ruta:

     base=${file%.*} #${base} is now 'file'. 

Usando basename utilicé lo siguiente para lograr esto:

 for file in *; do ext=${file##*.} fname=`basename $file $ext` # Do things with $fname done; 

Esto no requiere conocimiento a priori de la extensión de archivo y funciona incluso cuando tiene un nombre de archivo que tiene puntos en su nombre de archivo (delante de su extensión); sin embargo, requiere el basename del progtwig, pero esto es parte de los coreutils de GNU, por lo que debe enviarse con cualquier distribución.

Forma pura de bash:

 ~$ x="/foo/bar/fizzbuzz.bar.quux.zoom"; ~$ y=${x/\/*\//}; ~$ echo ${y/.*/}; fizzbuzz 

Esta funcionalidad se explica en man bash en “Expansión de parámetros”. Abundan las formas no bash: awk, perl, sed, etc.

EDITAR: Funciona con puntos en sufijos de archivo y no necesita saber el sufijo (extensión), pero no funciona con puntos en el nombre mismo.

Las funciones basename y dirname son lo que buscas:

 mystring=/foo/fizzbuzz.bar echo basename: $(basename $mystring) echo basename + remove .bar: $(basename $mystring .bar) echo dirname: $(dirname $mystring) 

Tiene salida:

 basename: fizzbuzz.bar basename + remove .bar: fizzbuzz dirname: /foo 
 perl -pe 's/\..*$//;s{^.*/}{}' 

Usar el basename asume que sabes cuál es la extensión del archivo, ¿no es así?

Y creo que las diversas sugerencias de expresiones regulares no son compatibles con un nombre de archivo que contenga más de un “.”

Lo siguiente parece lidiar con puntos dobles. Ah, y nombres de archivo que contienen un “/” ellos mismos (solo para patadas)

Parafraseando a Pascal, “Lo siento, este guión es tan largo. No tuve tiempo para hacerlo más corto”

 #!/usr/bin/perl $fullname = $ARGV[0]; ($path,$name) = $fullname =~ /^(.*[^\\]\/)*(.*)$/; ($basename,$extension) = $name =~ /^(.*)(\.[^.]*)$/; print $basename . "\n"; 

Si no puede usar el nombre base como se sugiere en otras publicaciones, siempre puede usar sed. Aquí hay un ejemplo (feo). No es el mejor, pero funciona extrayendo la cadena deseada y reemplazando la entrada con la cadena deseada.

 echo '/foo/fizzbuzz.bar' | sed 's|.*\/\([^\.]*\)\(\..*\)$|\1|g' 

Lo cual te dará la salida

fizzbuzz

Tenga cuidado con la solución de perl sugerida: elimina cualquier cosa después del primer punto.

 $ echo some.file.with.dots | perl -pe 's/\..*$//;s{^.*/}{}' some 

Si quieres hacerlo con Perl, esto funciona:

 $ echo some.file.with.dots | perl -pe 's/(.*)\..*$/$1/;s{^.*/}{}' some.file.with 

Pero si está utilizando Bash, las soluciones con y=${x%.*} (O el basename "$x" .ext si conoce la extensión) son mucho más simples.

Combinando la respuesta mejor calificada con la segunda mejor calificada para obtener el nombre de archivo sin la ruta completa:

 $ x="/foo/fizzbuzz.bar.quux" $ y=(`basename ${x%%.*}`) $ echo $y fizzbuzz 

El nombre de base hace eso, elimina la ruta. También eliminará el sufijo si está dado y si coincide con el sufijo del archivo pero necesitaría saber el sufijo para darle al comando. De lo contrario, puede usar mv y descubrir cuál es el nuevo nombre de otra manera.

Las informaciones que puede encontrar en el manual de Bash , busque ${parameter%word} y ${parameter%%word} en la sección de coincidencia de la parte final.