472 Stimmen

Extrahieren von Dateibasisnamen ohne Pfad und Erweiterung in der Bash

Bei Dateinamen wie diesen:

/the/path/foo.txt
bar.txt

Ich hoffe es zu bekommen:

foo
bar

Warum funktioniert das nicht?

#!/bin/bash

fullfile=$1
fname=$(basename $fullfile)
fbname=${fname%.*}
echo $fbname

Was ist der richtige Weg, um das zu tun?

842voto

ghostdog74 Punkte 305138

Sie müssen den externen Anbieter nicht anrufen basename Befehl. Stattdessen könnten Sie die folgenden Befehle verwenden:

$ s=/the/path/foo.txt
$ echo "${s##*/}"
foo.txt
$ s=${s##*/}
$ echo "${s%.txt}"
foo
$ echo "${s%.*}"
foo

Beachten Sie, dass diese Lösung in allen neueren ( nach 2004 ) POSIX konforme Schalen (z. B. bash , dash , ksh , usw.).

Source : Shell-Befehlssprache 2.6.2 Parametererweiterung

Mehr über bash String Manipulationen: http://tldp.org/LDP/LG/issue18/bash.html

384voto

Michael Aaron Safyan Punkte 90663

En basename Befehl hat zwei verschiedene Aufrufe; in einem geben Sie nur den Pfad an, in diesem Fall erhalten Sie die letzte Komponente, während Sie im anderen Fall auch ein Suffix angeben, das entfernt wird. Sie können also Ihren Beispielcode vereinfachen, indem Sie den zweiten Aufruf von basename verwenden. Achten Sie auch auf die korrekte Zitierweise:

fbname=$(basename "$1" .txt)
echo "$fbname"

87voto

kom lim Punkte 761

Eine Kombination aus Basename und Cut funktioniert gut, auch bei Doppelendungen wie .tar.gz :

fbname=$(basename "$fullfile" | cut -d. -f1)

Es wäre interessant, ob diese Lösung weniger Rechenleistung benötigt als die Bash Parameter Expansion.

58voto

Hier sind Einzeiler:

  1. $(basename "${s%.*}")
  2. $(basename "${s}" ".${s##*.}")

Ich brauchte dies, das gleiche wie von bongbang und w4etwetewtwet gefragt.

26voto

agc Punkte 7474

Reines bash , nein basename , kein Jonglieren mit Variablen. Setzen Sie eine Zeichenfolge und echo :

p=/the/path/foo.txt
echo "${p//+(*\/|.*)}"

Salida:

foo

Anmerkung: Die bash extglob muss die Option "on" sein, ( Ubuntu setzt extglob "on" standardmäßig), wenn nicht, tun:

shopt -s extglob

Ein Spaziergang durch die ${p//+(*\/|.*)} :

  1. ${p -- beginnen Sie mit $p .
  2. // jede Instanz des folgenden Musters ersetzen.
  3. +( Spiel eine oder mehrere der Musterliste in Klammern, ( d.h. bis Punkt #7 unten).
  4. 1. Muster: *\/ passt auf alles, was vor einem wörtlichen " / " Zeichen.
  5. Schablonentrenner | die in diesem Fall wie eine logisches ODER .
  6. 2. Muster: .* passt auf alles nach einem wörtlichen " . " - das heißt, in bash die " . " ist nur ein Punktzeichen, und no ein Regex-Punkt .
  7. ) Ende Musterliste .
  8. } Parametererweiterung beenden. Bei einer Stringsubstitution gibt es normalerweise eine weitere / gefolgt von einer Ersatzzeichenfolge. Aber da es keine / dort werden die übereinstimmenden Muster durch nichts ersetzt; dadurch werden die Übereinstimmungen gelöscht.

Einschlägige man bash Hintergrund:

  1. Mustersubstitution :
  ${parameter/pattern/string}
          Pattern substitution.  The pattern is expanded to produce a pat
          tern just as in pathname expansion.  Parameter is  expanded  and
          the  longest match of pattern against its value is replaced with
          string.  If pattern begins with /, all matches  of  pattern  are
          replaced   with  string.   Normally  only  the  first  match  is
          replaced.  If pattern begins with #, it must match at the begin
          ning of the expanded value of parameter.  If pattern begins with
          %, it must match at the end of the expanded value of  parameter.
          If string is null, matches of pattern are deleted and the / fol
          lowing pattern may be omitted.  If parameter is @ or *, the sub
          stitution  operation  is applied to each positional parameter in
          turn, and the expansion is the resultant list.  If parameter  is
          an  array  variable  subscripted  with  @ or *, the substitution
          operation is applied to each member of the array  in  turn,  and
          the expansion is the resultant list.
  1. erweiterter Mustervergleich :
  If the extglob shell option is enabled using the shopt builtin, several
   extended  pattern  matching operators are recognized.  In the following
   description, a pattern-list is a list of one or more patterns separated
   by a |.  Composite patterns may be formed using one or more of the fol
   lowing sub-patterns:

          ?(pattern-list)
                 Matches zero or one occurrence of the given patterns
          *(pattern-list)
                 Matches zero or more occurrences of the given patterns
          +(pattern-list)
                 Matches one or more occurrences of the given patterns
          @(pattern-list)
                 Matches one of the given patterns
          !(pattern-list)
                 Matches anything except one of the given patterns

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X