2008-09-24 9 views

Respuesta

408

Así es como hacerlo con el signo # y% operadores 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 de que el primer punto.

Ejemplo:

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

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

+0

Terminé usando este porque era el más flexible y había un par de cosas similares que quería hacer, así que me fue muy bien. –

+0

Esta es probablemente la más flexible de todas las respuestas publicadas, pero creo que las respuestas que sugieren los comandos basename y dirname también merecen algo de atención. Ellos pueden ser el truco si no necesita ninguna otra coincidencia de patrón de lujo. – mgadda

+3

¿Cómo se llama esto $ {x% .bar}? Me gustaría aprender más al respecto. – Basil

170

vistazo a la orden nombre base:

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

Probablemente la más simple de todas las soluciones actualmente ofrecidas ... aunque usaría $ (...) en lugar de backticks. –

+6

Más simple, pero agrega una dependencia (no es una gran ni extraña, lo admito). También necesita saber el sufijo. –

+0

Y se puede usar para eliminar cualquier cosa del extremo, básicamente solo hace una extracción de cadena desde el final. – Smar

12

forma pura fiesta:

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

Esta funcionalidad se explica en el manual de bash en "la expansión de parámetro". Abundan las formas no bash: awk, perl, sed, etc.

EDIT: funciona con los puntos en el archivo sufijos y no necesita saber el sufijo (extensión), pero no se trabajo con puntos en el nombre sí .

3
perl -pe 's/\..*$//;s{^.*/}{}' 
7

El nombre base y funciones dirname son lo que está buscando:

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

tiene una salida:

basename: fizzbuzz.bar 
basename + remove .bar: fizzbuzz 
dirname: /foo 
3

El uso de basename asume que usted sabe cuál es la extensión del archivo, ¿no es así?

Y creo que las diversas sugerencias de expresiones regulares no resuelven un nombre de archivo que contiene más de un "."

Lo siguiente parece hacer frente a los puntos dobles. Ah, y los nombres de archivo que contienen una "/" a sí mismos (sólo por diversión)

Parafraseando a Pascal, "Lo sentimos, este guión es tan larga. No he tenido tiempo para hacerla más corta"


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

Esto es bueno y robusto –

2

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' 

que le llevará la salida

FizzBuzz

+0

Aunque esta es la respuesta a la pregunta original, este comando es útil cuando tengo líneas de rutas en un archivo para extraer los nombres base para imprimirlos en la pantalla. –

0

El nombre base hace eso, elimina la vía. 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.

2

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

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

Si quiere hacerlo con el Perl, esto funciona:

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

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

10

Utilizando nombre base que utiliza lo siguiente para lograrlo:

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

    # Do things with $fname 
done; 

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

+1

¡Excelente respuesta! elimina la extensión de una manera muy limpia, pero no elimina el. al final del nombre de archivo. – metrix

+1

@metrix acaba de agregar el "." antes $ ext, es decir: 'fname = \' nombre base $ archivo. $ ext \ '' –

28

fiesta puro, hecho en dos operaciones separadas:

  1. elimine la ruta de un camino de cuerdas:

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

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

Combinando la t op-respuesta nominal con la respuesta de segundo más altas calificaciones para obtener el nombre del archivo sin la ruta completa:

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

informaciones que puede encontrar en Bash manual, busque ${parameter%word} y ${parameter%%word} en la sección posterior a juego porción.

Cuestiones relacionadas