Wie kann ich mit sed nur den Dateinamen ermitteln? Ich habe das
out_file=$(echo $in_file|sed "s/\(.*\.\).*/\1mp4/g")
Aber ich verstehe den Weg auch /root/video.mp4
und ich will nur video.mp4
.
basename
von den GNU- Coreutils können Ihnen dabei helfen:
$ basename /root/video.mp4
video.mp4
Wenn Sie die Erweiterung der Datei bereits kennen, können Sie sie basename
mithilfe der Syntax aufrufen basename NAME [SUFFIX]
, um sie zu entfernen:
$ basename /root/video.mp4 .mp4
video
Oder eine andere Option wäre, alles nach dem letzten Punkt zu schneiden sed
:
$ basename /root/video.old.mp4 | sed 's/\.[^.]*$//'
video.old
sed 's/\.[^.]*$//'
wie Sie haben, wird fehlschlagen für (versteckte).filename
und.
und..
VerzeichnisseDie einfachste Lösung ist, alles bis zum letzten Auftreten von
/
:echo /root/video.mp4 | sed 's/.*\///'
quelle
Verwenden Sie eine der folgenden Möglichkeiten:
ps. Sie erhalten dieselbe Zeichenfolge, da sie in Ihrer Anweisung
\(.*\.\)
vom Anfang bis zum Punkt (/root/video.
) mit der Zeichenfolge übereinstimmt. Anschließend fügen Sie manuell.mp4
die Zeichenfolge hinzu, die der ursprünglichen Zeichenfolge entspricht. Sie solltens=.*\([^/]*\)=\1=
stattdessen verwenden.Update: (Erstes ist jetzt behoben)
Um den einzigen Dateinamen ohne Erweiterung zu erhalten, können Sie:
quelle
my.file.tar.gz
.sed
undawk
. Fest. Vielen Dank.Eine der Grundlagen für die Verwendung von Regex ist, dass Muster bei der Angabe der Platzhalter von Natur aus gierig sind. Die von @uloBasEI vorgeschlagene Antwort ist sicherlich eine funktionierende Antwort, erfordert jedoch auch die Verwendung des Befehls basename. Die ursprüngliche Frage von @Shixons fordert eine Lösung, die nur sed verwendet.
Bevor Sie fortfahren, ist es immer hilfreich zu wissen, welche Version von sed das Ziel ist. Ich gehe von BSD aus (wie mit OSX ausgeliefert).
Erstens funktioniert das in der ursprünglichen Frage vorgeschlagene Muster nicht, da es vom Anfang der Eingabezeichenfolge bis einschließlich des letzten Punkts alles erfasst. Ohne Anker verschluckt diese Suche alles von links nach rechts. Das mit "/ 1" übereinstimmende Muster ist daher alles bis einschließlich des letzten Punkts. Sogar ein Dateiname mit mehreren Punkten wird als Ganzes verschluckt. Überhaupt nicht das gewünschte Ergebnis.
Der erste Schritt ist die Festlegung einer Strategie zur Identifizierung von Mustern. Hier möchten Sie alles loswerden, was links vom Dateinamen steht (wir werden uns später mit der Erweiterung befassen):
Die Suche beginnt am Anfang der Zeichenfolge. Es entspricht einem Muster von "/.*" null oder mehrmals und löscht anschließend alles. Wir drucken die passenden Muster mit "\ 1". Wir suchen nicht global; Wir suchen ab dem Anfang der Zeichenfolge, indem wir den Anker ^ angeben.
Wir erhalten eine bessere Übersichtlichkeit, indem wir die Option "-E" aktivieren, damit wir Klammern nicht umgehen müssen:
Jetzt haben wir den Teil auf der linken Seite. Fügen wir das Teil rechts hinzu. Beachten Sie, dass wir den linken Teil als Muster behalten müssen, da wir so festlegen können, dass er null oder mehrmals vorkommt. Jetzt fügen wir nur noch ein Muster für den Teil rechts hinzu:
Wir drucken nur die zweite Übereinstimmung aus und verwerfen dabei alles außer dem Dateinamen. Die Dateinamenerweiterung muss jedoch noch entfernt werden.
Das "$" am Ende ist optional.
Zum Schluss überarbeiten Sie die neue Erweiterung wie folgt:
Eine zusätzliche Optimierung besteht darin, den ersten Schrägstrich optional zu machen, um relative Pfade zu behandeln:
Ich bin auf diese Frage gestoßen, weil ich faul war, als ich nach einem Sed-Muster suchte, um den Basisnamen zu ersetzen . Ich arbeite an einem abgespeckten System, auf dem dieser Befehl nicht installiert ist.
quelle