Holen Sie sich den Teil einer Zeile vor dem letzten Schrägstrich

7

Ich versuche, ein Conky-Skript zu schreiben, das mein MPD-Albumcover zeigt, eine 'folder.jpg' im Albumordner. Mein aktueller Plan ist es mpc -f %file%, den Dateinamen und den Pfad auszudrucken und dann den tatsächlichen Dateinamen (dh alles nach dem letzten /) auszuschneiden und diesen als Pfad für das Bildobjekt von conky zu verwenden.

Ich habe Probleme mit grep / cut, insbesondere da einige Songs in zwei Ordnern verschachtelt sind, während andere in einem sind. ( grep -m 1 . |cut -f1 -d /funktioniert für die Einzelordner-Alben)

Wie würde ich das machen? Gibt es einen einfacheren Weg, den ich vermisse?

rargh
quelle
Möchten Sie den Verzeichnisteil bis zum letzten /oder den Dateinamen ohne führende Verzeichnisteile? "Ausschneiden" ist mehrdeutig und wir haben es anders interpretiert.
Gilles 'SO - hör auf böse zu sein'
@ Gilles Aus seinem Beispiel mit Alben mit einem Ordner möchte das OP den Teil vor dem letzten Schrägstrich behalten.
vinc17

Antworten:

9

Sie können sedden Rest entfernen - alles beginnend mit dem letzten Schrägstrich :

mpc -f %file% | head -1 | sed 's:/[^/]*$::'

Das Muster /[^/]*$entspricht einem Schrägstrich, gefolgt von allen Zeichen außer Schrägstrich, bis zum Ende der Zeile. Es wird durch die leere Zeichenfolge ersetzt.
Das head -1ignoriert einige Statusausgaben, die der gewünschten Zeile folgen - aber siehe unten, wie man sie überhaupt nicht pringt.

Falls Sie nicht an sed gewöhnt sind, kann der Befehl aufgrund der :verwendeten ungewöhnlich aussehen . Möglicherweise haben Sie zuvor sedBefehle mit /als Trennzeichen gesehen, z. B. 's/foo/bar/'- Ich bevorzuge die Verwendung des Trennzeichens :zur besseren Lesbarkeit, da der Ausdruck sich /selbst enthält . Alternativ könnten wir dem /im Ausdruck entgehen : 's/\/[^\/]*$//'- das macht es nicht lesbarer.


Die Art und Weise, wie Sie es verwenden, mpcbietet Ihnen zwei zusätzliche Statuszeilen. Die Option -qfür leise schaltet den gesamten Ausgang aus. Sie müssen -qdie aktuelle Wiedergabedatei explizit drucken, um die gewünschte Zeile zu erhalten, und nicht mehr:

mpc -q -f %file% current | sed 's:/[^/]*$::'

Anstatt alles zu entfernen , das mit dem letzten Schrägstrich beginnt , könnte man alles explizit vor dem letzten Schrägstrich drucken :

mpc -q -f %file% current | sed 's:^\(.*\)/.*$:\1:'

Dies entspricht allen Zeichen, denen ein /und andere Zeichen folgen . Es stimmt so gut wie möglich überein, so dass das /, was übereinstimmt, das letzte ist.

Volker Siegel
quelle
Vielen Dank. Die -q-Flagge hat auch sehr geholfen.
selten
3

Wenn Sie diese Regel auf eine einzelne Zeichenfolge anwenden möchten, können Sie anstelle von sed(siehe die andere Antwort) den folgenden dirnameBefehl verwenden:

$ dirname "1 2/3 4/5 6/file"
1 2/3 4/5 6
vinc17
quelle
2

Grep ist nicht das letzte Werkzeug für diesen Job. grep -m 1 .druckt die erste nicht leere Zeile, was nicht sinnvoll ist. Sie können komplexe Lösungen erstellen, die grep und andere Tools umfassen. Der einfache Weg ist jedoch sed . Eine Möglichkeit besteht darin, eine letzte Folge von Nicht-Schrägstrich-Zeichen sowie den vorhergehenden Schrägstrich durch die leere Zeichenfolge zu ersetzen:

mpc -f %file% | sed 's:/[^/]*$::'

Alternativ können Sie alles bis zum letzten Schrägstrich beibehalten und Folgendes verwerfen:

mpc -f %file% | sed 's:^\(.*\)\(/.*\)$:\1:'

Beachten Sie, dass beide Methoden die Eingabe unverändert lassen, wenn sie kein enthält /, dh wenn Sie einen Dateinamen ohne Verzeichnisangabe übergeben. Während Sie dies in sed lösen können, wenn es ein Problem ist, ist es einfacher, den dirnameBefehl aufzurufen :

dirname -- "$(mpc -f %file%)"

In einem Shell-Skript können Sie auch Parametererweiterungskonstrukte verwenden. Dies ist jedoch komplexer, wenn Sie nur das Ergebnis ausdrucken möchten:

full_path="$(mpc -f %file%)"
case "$full_path" in
  */*) directory_part="${full_path%/*}"
  *) directory_part="."
printf '%s\n' "$directory_part"
Gilles 'SO - hör auf böse zu sein'
quelle