Am Ende habe ich dieses verwendet, weil es am flexibelsten war und es noch ein paar ähnliche Dinge gab, die ich auch tun wollte, damit dies gut funktioniert.
Lawrence Johnston
Dies ist wahrscheinlich die flexibelste aller veröffentlichten Antworten, aber ich denke, dass die Antworten, die die Befehle basename und dirname vorschlagen, ebenfalls einige Aufmerksamkeit verdienen. Sie können nur der Trick sein, wenn Sie keinen anderen ausgefallenen Musterabgleich benötigen.
mgadda
7
Wie heißt das $ {x% .bar}? Ich würde gerne mehr darüber erfahren.
Basil
14
@Basil: Parametererweiterung. Geben Sie auf einer Konsole "man bash" und dann "/ parameter extension" ein
Zan Lynx
1
Ich denke, die "Man Bash" -Erklärung ist sinnvoll, wenn Sie bereits wissen, was es tut, oder wenn Sie es selbst auf die harte Tour ausprobiert haben. Es ist fast so schlimm wie Git Referenz. Ich würde es stattdessen einfach googeln.
Wahrscheinlich die einfachste aller derzeit angebotenen Lösungen ... obwohl ich $ (...) anstelle von Backticks verwenden würde.
Michael Johnson
6
Am einfachsten, fügt aber eine Abhängigkeit hinzu (keine große oder seltsame, gebe ich zu). Es muss auch das Suffix kennen.
Vinko Vrsalovic
Und kann verwendet werden, um alles vom Ende zu entfernen. Im Grunde genommen wird nur eine Zeichenfolge vom Ende entfernt.
Smar
2
Das Problem ist der Zeitschlag. Ich habe gerade die Frage nach dieser Diskussion durchsucht, nachdem Bash fast 5 Minuten gebraucht hatte, um 800 Dateien mit dem Basisnamen zu verarbeiten. Unter Verwendung der obigen Regex-Methode wurde die Zeit auf etwa 7 Sekunden reduziert. Obwohl diese Antwort für den Programmierer einfacher durchzuführen ist, ist der Zeitaufwand einfach zu groß. Stellen Sie sich einen Ordner mit ein paar tausend Dateien vor! Ich habe einige solche Ordner.
Xizdaqrian
@ xizdaqrian Das ist absolut falsch. Dies ist ein einfaches Programm, dessen Rückkehr keine halbe Sekunde dauern sollte. Ich habe gerade time find / home / me / dev -name "* .py" .py -exec basename {} \; und es entfernte die Erweiterung und das Verzeichnis für 1500 Dateien in insgesamt 1 Sekunde.
Laszlo Treszkai
40
Pure Bash, durchgeführt in zwei getrennten Operationen:
Entfernen Sie den Pfad aus einer Pfadzeichenfolge:
path=/foo/bar/bim/baz/file.gif
file=${path##*/} #$file is now 'file.gif'
Entfernen Sie die Erweiterung aus einer Pfadzeichenfolge:
Mit dem Basisnamen habe ich Folgendes verwendet, um dies zu erreichen:
for file in*;do
ext=${file##*.}
fname=`basename $file $ext`# Do things with $fnamedone;
Dies erfordert keine vorherige Kenntnis der Dateierweiterung und funktioniert auch dann, wenn Sie einen Dateinamen haben, dessen Dateiname Punkte enthält (vor der Erweiterung). es erfordert das Programmbasename , aber dies ist Teil der GNU-Coreutils, daher sollte es mit jeder Distribution ausgeliefert werden.
Es wäre hilfreich, das Zitat hier zu korrigieren - führen Sie dies möglicherweise über shellcheck.net mit mystring=$1dem aktuellen konstanten Wert aus (wodurch mehrere Warnungen unterdrückt werden, wobei sichergestellt ist , dass keine Leerzeichen / Glob-Zeichen / usw. enthalten sind), und beheben Sie die Probleme findet?
Charles Duffy
Nun, ich habe einige entsprechende Änderungen vorgenommen, um Anführungszeichen in $ mystring zu unterstützen.
Meine Güte, das ist
Es wäre eine weitere Verbesserung, die Ergebnisse zu zitieren: echo "basename: $(basename "$mystring")"- Auf diese Weise, wenn mystring='/foo/*'Sie die *Dateien nachbasename Abschluss nicht durch eine Liste von Dateien im aktuellen Verzeichnis ersetzen lassen .
Charles Duffy
6
Verwenden von basename davon , dass Sie die Dateierweiterung kennen, nicht wahr?
Und ich glaube, dass die verschiedenen Vorschläge für reguläre Ausdrücke nicht mit einem Dateinamen fertig werden, der mehr als ein "enthält".
Das Folgende scheint mit Doppelpunkten fertig zu werden. Oh, und Dateinamen, die selbst ein "/" enthalten (nur für Tritte)
Um Pascal zu paraphrasieren: "Entschuldigung, dieses Skript ist so lang. Ich hatte keine Zeit, es kürzer zu machen."
Dies kann sogar -zdatensamensicher gemacht werden, indem die Ausgabe mit der Option durch NUL-Bytes getrennt wird , beispielsweise für diese Dateien, die Leerzeichen, Zeilenumbrüche und Glob-Zeichen enthalten (zitiert durch ls):
$ ls has*'has'$'\n''newline.bar''has space.bar''has*.bar'
Wenn Sie den in anderen Posts vorgeschlagenen Basisnamen nicht verwenden können, können Sie immer sed verwenden. Hier ist ein (hässliches) Beispiel. Es ist nicht das Beste, 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'
Obwohl dies die Antwort auf die ursprüngliche Frage ist, ist dieser Befehl nützlich, wenn ich Pfadzeilen in einer Datei habe, um Basisnamen zu extrahieren und sie auf dem Bildschirm auszudrucken.
Sangcheol Choi
2
Hüten Sie sich vor der vorgeschlagenen Perl-Lösung: Sie entfernt alles nach dem ersten Punkt.
$ echo some.file.with.dots | perl -pe 's/\..*$//;s{^.*/}{}'
some
Wenn Sie es mit Perl machen wollen, funktioniert dies:
Der Basisname macht das, entfernt den Pfad. Es wird auch das Suffix entfernt, wenn es angegeben ist und mit dem Suffix der Datei übereinstimmt, aber Sie müssten das Suffix kennen, das Sie dem Befehl geben können. Andernfalls können Sie mv verwenden und herausfinden, wie der neue Name anders lauten soll.
${parameter%word}
und${parameter%%word}
in Hinterteil Anpassungsabschnitt.Antworten:
Hier erfahren Sie, wie Sie dies mit den Operatoren # und% in Bash tun.
${x%.bar}
könnte auch sein${x%.*}
, alles nach einem Punkt${x%%.*}
zu entfernen oder alles nach dem ersten Punkt zu entfernen.Beispiel:
Die Dokumentation finden Sie im Bash-Handbuch . Sucht
${parameter%word}
und${parameter%%word}
Hinterteil Anpassungsabschnitt.quelle
Schauen Sie sich den Befehl basename an:
quelle
Pure Bash, durchgeführt in zwei getrennten Operationen:
Entfernen Sie den Pfad aus einer Pfadzeichenfolge:
Entfernen Sie die Erweiterung aus einer Pfadzeichenfolge:
quelle
Mit dem Basisnamen habe ich Folgendes verwendet, um dies zu erreichen:
Dies erfordert keine vorherige Kenntnis der Dateierweiterung und funktioniert auch dann, wenn Sie einen Dateinamen haben, dessen Dateiname Punkte enthält (vor der Erweiterung). es erfordert das Programm
basename
, aber dies ist Teil der GNU-Coreutils, daher sollte es mit jeder Distribution ausgeliefert werden.quelle
fname=`basename $file .$ext`
Pure Bash Way:
Diese Funktionalität wird auf man bash unter "Parametererweiterung" erläutert. Non-Bash-Wege gibt es zuhauf: awk, perl, sed und so weiter.
EDIT: Arbeiten mit Punkten in der Datei Suffixe und nicht das Suffix (Erweiterung) wissen müssen, aber nicht Arbeit mit Punkten im Namen selbst.
quelle
Die Funktionen basename und dirname sind genau das, wonach Sie suchen:
Hat Ausgabe:
quelle
mystring=$1
dem aktuellen konstanten Wert aus (wodurch mehrere Warnungen unterdrückt werden, wobei sichergestellt ist , dass keine Leerzeichen / Glob-Zeichen / usw. enthalten sind), und beheben Sie die Probleme findet?echo "basename: $(basename "$mystring")"
- Auf diese Weise, wennmystring='/foo/*'
Sie die*
Dateien nachbasename
Abschluss nicht durch eine Liste von Dateien im aktuellen Verzeichnis ersetzen lassen .Verwenden von
basename
davon , dass Sie die Dateierweiterung kennen, nicht wahr?Und ich glaube, dass die verschiedenen Vorschläge für reguläre Ausdrücke nicht mit einem Dateinamen fertig werden, der mehr als ein "enthält".
Das Folgende scheint mit Doppelpunkten fertig zu werden. Oh, und Dateinamen, die selbst ein "/" enthalten (nur für Tritte)
Um Pascal zu paraphrasieren: "Entschuldigung, dieses Skript ist so lang. Ich hatte keine Zeit, es kürzer zu machen."
quelle
Neben die POSIX - konformen Syntax in verwendete diese Antwort ,
wie in
GNU
basename
unterstützt eine andere Syntax:mit dem gleichen Ergebnis. Der Unterschied und Vorteil ist , dass
-s
bedeutet-a
, die mehrere Argumente unterstützt:Dies kann sogar
-z
datensamensicher gemacht werden, indem die Ausgabe mit der Option durch NUL-Bytes getrennt wird , beispielsweise für diese Dateien, die Leerzeichen, Zeilenumbrüche und Glob-Zeichen enthalten (zitiert durchls
):Einlesen in ein Array:
readarray -d
erfordert Bash 4.4 oder neuer. Für ältere Versionen müssen wir eine Schleife ausführen:quelle
quelle
Wenn Sie den in anderen Posts vorgeschlagenen Basisnamen nicht verwenden können, können Sie immer sed verwenden. Hier ist ein (hässliches) Beispiel. Es ist nicht das Beste, aber es funktioniert, indem die gewünschte Zeichenfolge extrahiert und die Eingabe durch die gewünschte Zeichenfolge ersetzt wird.
Welches erhalten Sie die Ausgabe
quelle
Hüten Sie sich vor der vorgeschlagenen Perl-Lösung: Sie entfernt alles nach dem ersten Punkt.
Wenn Sie es mit Perl machen wollen, funktioniert dies:
Wenn Sie jedoch Bash verwenden, sind die Lösungen mit
y=${x%.*}
(oderbasename "$x" .ext
wenn Sie die Erweiterung kennen) viel einfacher.quelle
Der Basisname macht das, entfernt den Pfad. Es wird auch das Suffix entfernt, wenn es angegeben ist und mit dem Suffix der Datei übereinstimmt, aber Sie müssten das Suffix kennen, das Sie dem Befehl geben können. Andernfalls können Sie mv verwenden und herausfinden, wie der neue Name anders lauten soll.
quelle
Kombinieren Sie die am besten bewertete Antwort mit der am zweitbesten bewerteten Antwort, um den Dateinamen ohne den vollständigen Pfad zu erhalten:
quelle