Come rimuovo il suffisso del file e la porzione del percorso da una stringa di percorso in Bash?

Dato un percorso di file di stringhe come “/foo/fizzbuzz.bar”, come dovrei usare bash per estrarre solo la porzione “fizzbuzz” di detta stringa?

Ecco come farlo con gli operatori # e% in Bash.

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

${x%.bar} potrebbe anche essere ${x%.*} per rimuovere tutto dopo un punto o ${x%%.*} per rimuovere tutto dopo il primo punto.

Esempio:

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

La documentazione può essere trovata nel manuale di Bash . Cerca ${parameter%word} e ${parameter%%word} sezione di corrispondenza della parte finale.

guarda il comando basename:

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

Pure bash, fatto in due operazioni separate:

  1. Rimuovi il percorso da una stringa di percorso:

     path=/foo/bar/bim/baz/file.gif file=${path##*/} #$file is now 'file.gif' 
  2. Rimuovi l’estensione da una stringa di percorso:

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

Usando basename ho usato quanto segue per ottenere questo:

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

Ciò non richiede alcuna conoscenza a priori dell’estensione del file e funziona anche quando si ha un nome file con punti nel suo nome file (di fronte all’estensione); tuttavia richiede il basename programma del programma, ma questo fa parte del coreutils GNU quindi dovrebbe essere spedito con qualsiasi distribuzione.

Puro modo bash:

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

Questa funzionalità è spiegata su man bash sotto “Parameter Expansion”. I modi non bash abbondano: awk, perl, sed e così via.

MODIFICA: funziona con i punti nei suffissi del file e non ha bisogno di conoscere il suffisso (estensione), ma non funziona con i punti nel nome stesso.

Le funzioni basename e dirname sono ciò che stai cercando:

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

Ha prodotto:

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

L’uso di basename presuppone che tu sappia qual è l’estensione del file, non è vero?

E credo che i vari suggerimenti di espressioni regolari non siano in grado di gestire un nome di file contenente più di un “.”

Quanto segue sembra affrontare i doppi punti. Oh, e nomi di file che contengono un “/” loro stessi (solo per i calci)

Per parafrasare Pascal, “Scusa questo script è così lungo. Non ho avuto il tempo di renderlo più breve”

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

Se non puoi usare basename come suggerito in altri post, puoi sempre usare sed. Ecco un (brutto) esempio. Non è il massimo, ma funziona estraendo la stringa desiderata e sostituendo l’input con la stringa desiderata.

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

Quale ti porterà l’output

FizzBuzz

Fai attenzione alla soluzione perl suggerita: rimuove qualsiasi cosa dopo il primo punto.

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

Se vuoi farlo con perl, questo funziona:

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

Ma se usi Bash, le soluzioni con y=${x%.*} (O basename "$x" .ext se conosci l’estensione) sono molto più semplici.

Combinare la risposta più votata con la risposta di seconda valutazione per ottenere il nome file senza il percorso completo:

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

Il basename fa ciò, rimuove il percorso. Rimuoverà anche il suffisso se fornito e se corrisponde al suffisso del file ma sarà necessario conoscere il suffisso da dare al comando. Altrimenti puoi usare mv e capire quale dovrebbe essere il nuovo nome in un altro modo.

Informazioni che puoi trovare nel manuale di Bash , cerca ${parameter%word} e ${parameter%%word} nella sezione di corrispondenza delle porzioni finali.