2008-09-24 18 views

Antwort

408

Hier ist, wie es mit den # und% Operatoren in Bash zu tun.

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

${x%.bar} könnte auch ${x%.*} sein, alles zu entfernen, nach einem Punkt oder ${x%%.*} alles nach dem ersten Punkt zu entfernen.

Beispiel:

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

Dokumentation finden Sie im Bash manual finden. Suchen Sie nach ${parameter%word} und ${parameter%%word} Trailing-Abschnitt passenden Abschnitt.

+0

Ich benutzte diese, weil sie am flexibelsten war und es gab ein paar andere ähnliche Dinge, die ich auch tun wollte, dass dies gut ging. –

+0

Dies ist wahrscheinlich die flexibelste aller geposteten Antworten, aber ich denke, die Antworten, die die Befehle basename und dirname vorschlagen, verdienen ebenfalls Aufmerksamkeit. Sie können nur der Trick sein, wenn Sie keinen anderen ausgefallenen Mustervergleich benötigen. – mgadda

+3

Wie heißt das $ {x% .bar}? Ich würde gerne mehr darüber erfahren. – Basil

170

Blick auf den Basisnamen Befehl:

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

Wahrscheinlich die einfachste aller derzeit angebotenen Lösungen ... obwohl ich $ (...) anstelle von Backticks verwenden würde. –

+6

Einfachste aber fügt eine Abhängigkeit hinzu (nicht eine große oder seltsame, ich gebe zu). Es muss auch das Suffix kennen. –

+0

Und kann verwendet werden, um alles vom Ende zu entfernen, im Grunde ist es nur eine Zeichenfolge Entfernung von Ende. – Smar

12

reine bash Weise:

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

Diese Funktionalität auf den Menschen bash unter "Parameter Expansion" erklärt. Non Bash Wege im Überfluss: awk, perl, sed und so weiter.

EDIT: Funktioniert mit Punkten in der Datei Suffixe und muss nicht mit dem Suffix (Erweiterung) kennen, aber nicht Arbeit mit Punkten im Namen selbst.

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

Die Basisnamen und dirname Funktionen sind, was Sie nach:

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

Ausgang hat:

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

Die Verwendung von basename setzt voraus, dass Sie wissen, was die Dateierweiterung ist, nicht wahr?

Und ich glaube, dass die verschiedenen regulären Ausdruck Vorschläge nicht mit einem Dateinamen mit mehr als einem "."

Folgendes scheint mit Doppelpunkten zu bewältigen. Oh, und Dateinamen, die ein „/“ selbst (nur für Kicks) enthalten

Um Pascal zu paraphrasieren: „Sorry dieses Skript ist so lang. Ich hatte keine Zeit, um es kürzer“


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

Das ist nett und robust –

2

Wenn Sie basename nicht wie in anderen Posts vorgeschlagen verwenden können, können Sie immer sed verwenden. Hier ist ein (hässliches) Beispiel. Es ist nicht das größte, aber es funktioniert, indem die gewünschte Zeichenfolge extrahiert und die Eingabe durch die gewünschte Zeichenfolge ersetzt wird.

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

dem Sie den Ausgang

fizzbuzz

+0

Obwohl dies die Antwort auf die ursprüngliche Frage ist, ist dieser Befehl nützlich, wenn ich Pfade in einer Datei habe, um Basisnamen zu extrahieren, um sie auf dem Bildschirm auszugeben. –

0

Die Basisnamen erhalten hat, dass der Pfad entfernt. Es wird auch das Suffix entfernen, wenn es angegeben wird und wenn es mit dem Suffix der Datei übereinstimmt, aber Sie müssen das Suffix kennen, das Sie dem Befehl geben können. Ansonsten kannst du mv verwenden und herausfinden, wie der neue Name sein sollte.

2

Vorsicht vor der vorgeschlagenen Perl-Lösung: Es entfernt alles nach dem ersten Punkt.

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

Wenn Sie es mit Perl tun wollen, das funktioniert:

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

Aber wenn Sie Bash verwenden, die Lösungen mit y=${x%.*} (oder basename "$x" .ext wenn Sie die Erweiterung wissen) sind viel einfacher.

10

Mit Basisnamen haben ich folgendes dies zu erreichen:

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

    # Do things with $fname 
done; 

Dies erfordert kein a-priori-Wissen über die Dateierweiterung und funktioniert auch, wenn Sie einen Dateinamen haben, die Punkte in seinen Dateinamen (vorne hat es ist Erweiterung); es erfordert jedoch das Programm basename, aber das ist Teil der GNU Coreutils, so sollte es mit jeder Distribution ausgeliefert werden.

+1

Ausgezeichnete Antwort! entfernt die Erweiterung auf eine sehr saubere Weise, aber es entfernt nicht die. am Ende des Dateinamens. – metrix

+1

@metrix fügen Sie einfach das "." vor $ ext, dh: 'fname = \ 'Basisname $ file. $ ext \' ' –

28

reine bash, in zwei getrennten Operationen durchgeführt:

  1. Entfernen Sie den Pfad von einem Pfad-string:

    path=/foo/bar/bim/baz/file.gif 
    
    file=${path##*/} 
    #$file is now 'file.gif' 
    
  2. Entfernen Sie die Erweiterung aus einem Pfad-string:

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

Kombinieren der t op-rated Antwort mit der zweit top-rated Antwort auf die Dateinamen zu erhalten, ohne den vollständigen Pfad:

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

Informationen Sie in Bash manual, suchen Sie nach ${parameter%word} und ${parameter%%word} in Hinterteil passenden Abschnitts finden können.