Entfernen eines bestimmten Teils des Dateinamens (was nach dem zweiten Bindestrich steht) für alle Dateien in einem Ordner

7

Ich verwende das Befehlszeilenprogramm youtube-dl, um Videos von YouTube herunterzuladen und daraus MP3s zu erstellen avconv. Ich mache das unter Ubuntu 14.04 und bin sehr zufrieden damit.

Das Dienstprogramm lädt die Dateien herunter und speichert sie unter folgendem Namensschema:

TITLE(artist-track)-ID.mp3

Ein tatsächlicher Dateiname sieht also so aus:

EPIC RAP BATTLE of MANLINESS-_EzDRpkfaO4.mp3

Einige andere Dateinamen im Ordner sehen folgendermaßen aus:

EPIC RAP BATTLE of MANLINESS-_EzDRpkfaO4.mp3
Martin Garrix - Animals (Official Video)-gCYcHz2k5x0.mp3
Stromae - Papaoutai-oiKj0Z_Xnjc.mp3

Das war zunächst kein Problem. Es hat mich nicht gestört, meine Musik in Rhytmbox zu hören. Aber wenn Sie zu einem Telefon oder einem anderen Gerät wechseln, ist es ziemlich verwirrend, einen so langen Namen zu sehen, und einige Spieler, wie die von Samsung, behandeln diesen letzten Teil (ID nach dem zweiten Strich) des Namens als Album oder so.

Ich möchte ein Bash-Skript erstellen, das entfernt, was nach dem zweiten Bindestrich im Namen für alle Dateien steht, damit sie wie folgt aussehen:

Von: Martin Garrix - Animals (Official Video)-gCYcHz2k5x0.mp3

Zu: Martin Garrix - Animals (Official Video).mp3

Ist es auch möglich youtube-dl, die ID von nun an auszuschließen?

Ich lade gerade mit dem Befehl herunter:

youtube-dl --extract-audio --audio-quality 0 --audio-format mp3 URL
Bodo
quelle
Wenn Sie nicht auf einem bashSkript bestehen, hilft der Dired-Modus von Emacs (insbesondere die Variante WDired für "Writable Dired"). Siehe hier: gnu.org/software/emacs/manual/html_node/emacs/Wdired.html . In WDired, Sie im Grunde bearbeiten einen Puffer ein enthält lsAusgang, dann C-c C-czu verpflichten , diese Änderungen am Dateisystem. Und Sie können alle Emacs-Goodies verwenden, insbesondere query-replaceund query-replace-regexp. (Und schreiben Sie auch eine kurze Elisp-Hilfsfunktion, um sie zu automatisieren, oder zeichnen Sie ein Tastaturmakro auf und speichern Sie es. Rufen Sie es dann sogar wie ein bashSkript aus der Shell auf !)
mbork
Ok danke für den Tipp. Könnte nützlich sein. Ich suchte nach einem Bash-Skript, um es problemlos unter einer Reihe von Verzeichnissen ausführen zu können.
Bodo
Dieser Link: masteringemacs.org/articles/2011/03/25/… enthält einige Informationen zum Bearbeiten von Dateien aus mehreren Verzeichnissen in einem Dired-Puffer. Wenn Sie also find(wie in GNU find) alle Ihre Dateien können, können Sie sogar die Ersetzungs-Engine ausführen nur einmal!
mbork
Bereits wie in der akzeptierten Antwort gelöst, denke ich, ich könnte dies verwenden, wenn ich wieder brauche :)
Bodo

Antworten:

4

sed kann dies in einer einzigen Zeile erreichen, wenn auch auf ziemlich verworrene Weise.

ls | sed 's/\(.*\)\(-.*\)/mv \"&\" \"\1.mp3\"/' | bash

Dies listet zuerst die Dateien im aktuellen Verzeichnis auf (vorausgesetzt, alle Dateien, die Sie umbenennen möchten, befinden sich im aktuellen Verzeichnis) und generiert dann mit dem Befehl s / regex / replace von sed einen sinnvollen Befehl mv, der dann an bash weitergeleitet wird, der ihn ausführt . Dies setzt voraus, dass alle Ihre Dateien die Form "AC.mp3" oder "A - BC.mp3" haben. So funktioniert es:

Der Regex-Teil des Befehls sed ist

\(.*\)\(-.*\)

Diese "gruppiert" den Namen in zwei Gruppierungen (getrennt durch Klammern): eine übereinstimmende ". *" (beliebige Anzahl von Zeichen) und eine andere übereinstimmende "-. *", ein Bindestrich, gefolgt von einer beliebigen Anzahl von beliebigen Zeichen. Beachten Sie, dass dies mit dem gesamten Dateinamen übereinstimmt (in zwei Gruppen). Beachten Sie auch, dass die erste Gruppe, da "gieriger" Regex verwendet wird, wie gewünscht mit "A" in "AC.mp3" und "A - B" übereinstimmt, nicht nur mit "A" in "A - BC.mp3".

Der Ersatzteil des Befehls sed ist

mv \"&\" \"\1.mp3\"/

Beachten Sie, dass ein & Zeichen sed anweist, das gesamte Muster einzufügen, das mit dem regulären Ausdruck übereinstimmt, in diesem Fall der gesamte Dateiname, und \ 1 sed anweist, den Teil des Dateinamens einzufügen, der der ersten Gruppierung ". *" Entspricht. Diese beiden werden mit einem vorhergehenden mv und einem nachfolgenden .mp3 mit maskierten Anführungszeichen kombiniert, um einen sinnvollen Umbenennungsbefehl zu erzeugen. Für "A - BC.mp3" erzeugt der vollständige sed-Befehl beispielsweise:

mv "A - B-C.mp3" "A - B.mp3"

Und schließlich wird all dies an bash weitergeleitet, das den Befehl mv (Umbenennen) problemlos ausführt.

icasdri
quelle
Danke, hat perfekt funktioniert (habe andere Methoden ausprobiert und mich "--NAME-- ist kein Verzeichnis" gespielt). Gibt es eine Möglichkeit, dies rekursiv zu tun? (Ich habe Titel in Unterverzeichnissen meines Musikordners angeordnet.
Bodo
Sie sollten dies rekursiv erreichen können, indem Sie ls einfach anweisen, alle Dateien mit ihrem vollständigen Pfad rekursiv aufzulisten. Wenn "ls -d -1 $ PWD / ** / *" anstelle von "ls" als erster Befehl verwendet wird, werden alle Dateien mit ihrem vollständigen Pfad unter Verwendung des rekursiven Globbing-Operators ** in allen Unterverzeichnissen aufgelistet, jedoch nicht im aktuellen Verzeichnis, obwohl ich empfehlen würde, es zuerst zu testen, um festzustellen, ob es vernünftig ist (dh den gesamten Befehl ohne die endgültige Weiterleitung an bash auszuführen). Beachten Sie, dass die Bash-Version> = 4 zur Unterstützung von rekursivem Globbing benötigt wird.
icasdri
11

Ich würde den Perl-basierten renameBefehl verwenden - zum Beispiel, um die kürzeste Folge von Wortzeichen zu entfernen, die -vor dem .mp3Suffix beginnen, könnten Sie versuchen

rename -nv -- 's/-\w+?[.]mp3$/.mp3/' *.mp3

Die nOption führt den Befehl im Trockenlaufmodus aus. Wenn die Übereinstimmungen korrekt angezeigt werden, entfernen Sie die nOption und führen Sie sie erneut aus.

Steeldriver
quelle
Sie könnten einfach \.anstelle von verwenden [.].
Nyuszika7h
8

Der Teil, den Sie nicht möchten, ist die Video-ID. Sie können die Ausgabevorlagenfunktion von youtube-dl verwenden:

--output "%(title)s"

Dies verwendet nur den Titel und lässt die ID weg. Führen Sie es youtube-dlohne Parameter aus, um andere Optionen anzuzeigen.

Sie können Ihre vorhandenen Downloads reparieren:

for i in *; do mv "$i" `basename "$i" .mp3 | cut -f -2 -d "-"`.mp3; done

(Dies entspricht Jakkes Antwort).

Roadmr
quelle
Vielen Dank für den ersten Befehl (um den Ausgabedateinamen zu bearbeiten). Ich würde upvoten, wenn ich könnte, aber noch nicht genug Repräsentanten haben (ich werde zurückkommen und upvoten, wenn ich haben werde). Es wurde keine akzeptierte Antwort gegeben, da der zweite Befehl "--NAME-- ist kein Verzeichnis" für jeden Track ausgab. Zur Behebung der bereits heruntergeladenen @ icasdri-Antwort hat funktioniert. Nochmals vielen Dank für das youtube-dl Argument Ding.
Bodo
1
Wenn ich zurückkomme, um etwas zu korrigieren, muss ich "% (Titel) s" in "% (Titel) s.% (Ext) s" ändern, weil ich mich darüber beschwerte, dass Audio und Video denselben Namen haben und nicht konvertieren können. Prost!
Bodo
Sicherere Version : mv -- "$i" "$(basename "$i" .mp3 | cut -f 2 -d "-")".mp3.
Nyuszika7h
3

Sie können dies mit diesem Befehl überprüfen:

for i in *.mp3; do echo "$(echo $i|cut -d- -f1,2).mp3"; done

Beachten Sie, dass Sie Dateinamen ohne 2 Bindestriche haben, sodass dies nicht für alle funktioniert.

Wenn Sie die Namen tatsächlich ändern möchten,

for i in *.mp3
do
  newname="$(echo $i|cut -d- -f1,2).mp3";
  mv $i $newname
done
Jakke
quelle
Wenn Sie auf Nummer sicher gehen möchten, machen Sie einen CP anstelle eines MV. Sie erhalten die Originaldateien, müssen diese aber wahrscheinlich später manuell entfernen
Jakke,
Sie sollten Ihren Kommentar über cpvs mvin Ihrer Antwort bearbeiten
chaskes
Danke für den Hinweis, ich werde neu sein, es sind 4 Leerzeichen ... habe nur manchmal ein Problem beim Zählen: D
Jakke
Sie sollten auch jede Variablenerweiterung und Befehlssubstitution doppelt in Anführungszeichen setzen. Und verwenden Sie es nur echofür einfachen Text, es ist nicht portierbar.
Nyuszika7h
0

Eine Lösung, die nur die Shell verwendet:

filename=foo-bar-baz

while read -rd-; do
    newname="${newname:+$newname-}$REPLY"
done <<< "$filename"

mv "$filename" "$newname"

Dies funktioniert, weil der Dateiname nicht mit einem Bindestrich endet und das letzte Token ignoriert wird.

nyuszika7h
quelle