Massenumbenennung, * nix Version


11

Ich suchte nach einer Möglichkeit, eine große Anzahl von Dateien mit ähnlichen Namen umzubenennen, ähnlich wie diese (eine Windows-bezogene Frage), außer dass ich * nix (Ubuntu und FreeBSD, getrennt) verwende. Um es zusammenzufassen: Wie benenne ich bei Verwendung der Shell (Bash, CSH usw.) eine Reihe von Dateien massenweise um, z. B. die folgenden Dateien:

Beethoven - Fur Elise.mp3
Beethoven - Mondscheinsonate.mp3
Beethoven - Ode an die Freude.mp3
Beethoven - Wut über den verlorenen Penny.mp3

wird so umbenannt?

Fur Elise.mp3
Moonlight Sonata.mp3
Ode an Joy.mp3
Wut über den verlorenen Penny.mp3

Der Grund, warum ich dies tun möchte, ist, dass diese Dateisammlung unter einem Verzeichnis mit dem Namen "Beethoven" (dh dem Präfix der Dateinamen) abgelegt wird und diese Informationen über den Dateinamen selbst redundant sind.

Antworten:


12

Das Umbenennungsprogramm macht, was Sie wollen.

Benutz einfach rename 's/Beethoven\ -\ //g' *.mp3


Können Sie bitte bearbeiten, um einen Link zum Dienstprogramm bereitzustellen, oder ist dies in beiden genannten Distributionen (Ubuntu und FreeBSD) Standard?
Chris W. Rea

1
Es kommt mit Perl. Debian verwendet es als Umbenennungsbefehl, daher vermute ich, dass Ubuntu dies auch tut. Es gibt einen anderen Befehl zum Umbenennen, der wertlos ist. Überprüfen Sie daher die Manpage.
Derobert

Wow, die Umbenennungssyntax sieht sehr ähnlich aus, um sie zu ersetzen: D
Dzung Nguyen

Der Port in / usr / ports / sysutils / rename funktionierte perfekt in FreeBSD
Josh W.

10

Wie so viele Dinge unter Linux / Unix gibt es mehr als einen Weg, dies zu tun!

Einige verwenden möglicherweise mmv (Masse mv).

Der Befehl zum Umbenennen oder Vornamen, der mit einigen Perl-Paketen (neueres Ubuntu und Debian) geliefert wird, kann dies ebenfalls tun.

prename 's/Beethoven\ -\ //g' Beethoven*.mp3

Beachten Sie, dass das Umbenennungstool unter Fedora 10 nicht dasselbe Programm ist und anders funktioniert. Es ist Teil eines anderen Pakets, util-linux-ng und kann hier gefunden werden .

Ich gehe oft nur aus Gewohnheit zur Shell, um eine Schleife zu machen (nachdem solche Werkzeuge nicht immer existierten).

mkdir -p Beethoven
for x in Beethoven\ -\ *
do
mv "$x" Beethoven/"${x/Beethoven - /}"
done

Dadurch wird das Beethoven-Verzeichnis erstellt und die Datei in das Verzeichnis / den Dateinamen verschoben, in dem der Dateiname das "Beethoven -" durch nichts ersetzt hat.

Als Test vor:

$ ls
Beethoven - Fur Elise.mp3                 Beethoven - Ode to Joy.mp3
Beethoven - Moonlight Sonata.mp3          Beethoven - Rage Over the Lost Penny.mp3

Nach:

$ ls Beethoven/
Fur Elise.mp3                 Ode to Joy.mp3
Moonlight Sonata.mp3          Rage Over the Lost Penny.mp3

4

Probieren Sie diese Lösung aus, die mit einer Kombination aus grep und rename implementiert wurde. Dies setzt voraus, dass Sie eine ganze Reihe von Verzeichnissen haben, die Sie umbenennen müssen. Wenn es nur wenige gibt, würde ich den manuellen Ansatz wählen, wobei das "Artist -" - Muster für jedes fest codiert ist.

# Rename any mp3 files in the directory hierarchy of type "a - b.mp3" to "b.mp3"
find . -name "*.mp3" -exec rename -n -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;

Erläuterung von find :
Der Befehl find findet alle Dateien mit der Erweiterung .mp3 in der aktuellen Dateihierarchie und ruft das an jede übergebene Argument für -exec auf. Beachten Sie, dass innerhalb -exec , {} auf das Argument von geben verweist Fund (Dateipfad + Name). Die \;Sorgt für die ;wird übergeben benennen und stattdessen das Ende des von Anzeigen finden Befehl.

Der oben angegebene Befehl hat den Schalter -n (keine Aktion). Daher wird es Ihnen nur sagen, was passieren würde, wenn Sie es ausführen würden. Ich empfehle, diesen Befehl ohne den Schalter -n erst auszuführen, nachdem Sie ihn einmal ausgeführt haben und mit den vorgeschlagenen Ergebnissen zufrieden sind.

Nun zum regulären Ausdruck.

  • ^ entspricht dem Stringanfang.
  • $ stimmt mit dem Ende der Zeichenfolge überein.
  • . passt zu einem beliebigen Zeichen.
  • *bedeutet null oder mehr des vorhergehenden Konstrukts. .*bedeutet zB null oder mehr Zeichen.
  • \s steht für jedes Leerzeichen.
  • \S steht für jedes Nicht-Leerzeichen.
  • Alles , was in ()wird erfasst und als reflektierte $1, $2in Abhängigkeit von seiner Position.

Der reguläre Ausdruck:

  • Sucht zu Beginn nach einer optionalen Verzeichnisstruktur und erfasst diese in $ 1: (.*/)
  • Überspringt alles bis zum " -":.*-
  • Erfasst den Rest der Zeichenfolge mit Ausnahme der führenden und nachfolgenden Leerzeichen in $ 2: (.*)
  • Schreibt die Datei als $ 1 $ 2 um. Dies sollte "/path/to/file/""filename.mp3" sein.

Hier ist mein Testlauf:

/tmp/test$ ls -R
.:
a  b  c  z-unknown.mp3

./a:
a3.mp3                 a - longer title3.mp3  c.mp3   disc2
a - longer title2.mp3  a - long title.mp3     disc 1  the band - the title.mp3

./a/disc 1:
a - title1.mp3  a - title2.mp3

./a/disc2:
a - title1.mp3  a - title2.mp3

./b:
cd - ab - title3.mp3  cd - title1.mp3  cd - title2.mp3  c.mp3

./c:
c-pony2.mp4  c - pony3.mp3  c - pony4.mp3  c-pony.mp3

/tmp/test$ find . -name "*.mp3" -exec rename -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;
./c/c-pony.mp3 renamed as ./c/pony.mp3
./c/c - pony4.mp3 renamed as ./c/pony4.mp3
./c/c - pony3.mp3 renamed as ./c/pony3.mp3
./z-unknown.mp3 renamed as ./unknown.mp3
./a/the band - the title.mp3 renamed as ./a/the title.mp3
./a/a - longer title2.mp3 renamed as ./a/longer title2.mp3
./a/a - longer title3.mp3 renamed as ./a/longer title3.mp3
./a/disc 1/a - title1.mp3 renamed as ./a/disc 1/title1.mp3
./a/disc 1/a - title2.mp3 renamed as ./a/disc 1/title2.mp3
./a/a - long title.mp3 renamed as ./a/long title.mp3
./a/disc2/a - title1.mp3 renamed as ./a/disc2/title1.mp3
./a/disc2/a - title2.mp3 renamed as ./a/disc2/title2.mp3
./b/cd - title1.mp3 renamed as ./b/title1.mp3
./b/cd - title2.mp3 renamed as ./b/title2.mp3
./b/cd - ab - title3.mp3 renamed as ./b/title3.mp3

/tmp/test$ ls -R
.:
a  b  c  unknown.mp3

./a:
a3.mp3  c.mp3  disc 1  disc2  longer title2.mp3  longer title3.mp3  long title.mp3  the title.mp3

./a/disc 1:
title1.mp3  title2.mp3

./a/disc2:
title1.mp3  title2.mp3

./b:
c.mp3  title1.mp3  title2.mp3  title3.mp3

./c:
c-pony2.mp4  pony3.mp3  pony4.mp3  pony.mp3

Regexp's sind eine knifflige Angelegenheit, und ich habe so manche Fehler gemacht, als ich sie geschrieben habe. Daher würde ich jede Eingabe über den Mangel an Verdienst dieser begrüßen. Ich weiß, dass ich einige Tests gefunden habe.


1

Ich habe ein Java-Befehlszeilenprogramm zusammengestellt, mit dem das Umbenennen von Dateien (und Verzeichnissen) zum Kinderspiel wird, insbesondere für die Skripterstellung. Es ist kostenlos und Open Source, sodass Sie es nach Herzenslust ändern können:

RenameWand
http://renamewand.sourceforge.net/

Einige relevante Anwendungsbeispiele:

Verschieben Sie Dateien des Formulars "<a> - <b>"in das entsprechende Verzeichnis "<a>":

java -jar RenameWand.jar  "<a> - <b>"  "<a>/<b>"

Sortieren Sie die Dateien nach der zuletzt geänderten Zeit und benennen Sie sie mit einer dreistelligen Nummer um:

java -jar RenameWand.jar  "<a>"  "<3|#FT> <a>"

Ordnen Sie Teile des Dateinamens neu an und ändern Sie die Groß- und Kleinschreibung:

java -jar RenameWand.jar  "<album> - <artist> - <song>.<ext>" 
                          "<artist.upper> <album.title> - <song>.<ext.lower>"

1

zmv Das zsh-Umbenennungstool ist sehr gut.

# zmv "programmable rename"
# Replace spaces in filenames with a underline
zmv '* *' '$f:gs/ /_'
# Change the suffix from *.sh to *.pl
zmv -W '*.sh' '*.pl'
# lowercase/uppercase all files/directories
$ zmv '(*)' '${(L)1}' # lowercase
$ zmv '(*)' '${(U)1}' # uppercase

Weitere Notizen hier ...


0

Für Pinguinköpfe ist dies einfach in einem Shell-Skript oder AWK-Skript möglich. Für uns Sterbliche möchten Sie vielleicht Midnight Commander ausprobieren. Es ist auf den meisten Linux-Distributionen von einer Shell-Eingabeaufforderung vom Typ mc -a. Sie können Dateien mit regulären Ausdrücken umbenennen. Ich habe den Artikel unter GeekStuff http://www.thegeekstuff.com/2009/06/how-to-rename-files-in-group/ verwendet , um mir zu helfen.


0

Hier ist ein einfaches Befehlszeilenbeispiel. Ich hatte das Wort "weiß" in der Mitte der Namen einer Reihe von PNG-Dateien. Ich wollte es herausnehmen und nur einen einzigen Unterstrich hinterlassen. Das hat den Trick gemacht:

for i in *.png; do mv "$i" "${i/white/}"; done

0

Verwenden Sie vidir und verwenden Sie dann Ihre Editorfunktionen , um das Umbenennungsmuster anzuwenden.

NAME

vidir - Verzeichnis bearbeiten

ZUSAMMENFASSUNG

vidir [--verbose] [Verzeichnis | Datei | -] ...

BESCHREIBUNG

Mit vidir können Sie den Inhalt eines Verzeichnisses in einem Texteditor bearbeiten. Wenn kein Verzeichnis angegeben ist, wird das aktuelle Verzeichnis bearbeitet.

Beim Bearbeiten eines Verzeichnisses wird jedes Element im Verzeichnis in einer eigenen nummerierten Zeile angezeigt. Mit diesen Zahlen verfolgt vidir, welche Elemente geändert wurden. Löschen Sie Zeilen, um Dateien aus dem Verzeichnis zu entfernen, oder bearbeiten Sie Dateinamen, um Dateien umzubenennen. Sie können auch Zahlenpaare wechseln, um Dateinamen auszutauschen.

Beachten Sie, dass wenn "-" als zu bearbeitendes Verzeichnis angegeben ist, eine Liste von Dateinamen aus stdin gelesen und diese zur Bearbeitung angezeigt werden. Alternativ kann eine Liste von Dateien in der Befehlszeile angegeben werden.

BEISPIELE

vidir vidir * .jpeg Typische Verwendungen.

finden | vidir - Bearbeiten Sie auch den Inhalt des Unterverzeichnisses. Um Unterverzeichnisse zu löschen, löschen Sie den gesamten Inhalt und das Unterverzeichnis selbst im Editor.

find -type f | vidir - Bearbeiten Sie alle Dateien im aktuellen Verzeichnis und in den Unterverzeichnissen.

AUTOR

Joey Hess 2006-2010

Änderungen von Magnus Woldrich 2011

URHEBERRECHTE ©

Copyright 2006-2011 das Video "AUTOR" wie oben aufgeführt.

Lizenziert unter der GNU GPL.


0

Auf einem * nix ohne Perl renameverfügbar

Unter einigen * nix ist keine Umbenennung verfügbar, daher muss die Umbenennung mit einer anderen Methode durchgeführt werden. Vor ein paar Jahren habe ich zmvhier vorgeschlagen , was zwar großartig ist, aber auch nicht unbedingt verfügbar ist.

Mit Builtins und Sed können wir schnell ein Shell-Skript erstellen, das uns eine sehr ähnliche Syntax wie das Perl-Umbenennungsskript bietet.

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      mv -v "$file" "$(sed $sed_pattern <<< $file)"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

Verwendung

sedrename 's/Beethoven\ -\ //g' *.mp3

before:

./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3

after:

./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

Angenommen, wir wollten auch Zielordner erstellen ...

Da mvkeine Ordner erstellt werden, die wir nicht verwenden können, sedrenamewie es hier ist, aber es ist eine ziemlich kleine Änderung, daher denke ich, dass es schön wäre, sie auch einzuschließen.

Wir benötigen eine Dienstprogrammfunktion abspath(oder einen absoluten Pfad), damit wir die Zielordner für ein sed / rename-Muster generieren können, das eine neue Ordnerstruktur enthält.

abspath () { case "$1" in
               /*)printf "%s\n" "$1";;
               *)printf "%s\n" "$PWD/$1";;
             esac; }

Dadurch wird sichergestellt, dass wir die Namen unserer Zielordner kennen. Wenn wir umbenennen, müssen wir es für den Namen der Zieldatei verwenden.

# generate the rename target
target="$(sed $sed_pattern <<< $file)"

# Use absolute path of the rename target to make target folder structure
mkdir -p "$(dirname $(abspath $target))"

# finally move the file to the target name/folders
mv -v "$file" "$target"

Hier ist das vollständige Ordner-fähige Skript ...

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      target="$(sed $sed_pattern <<< $file)"
      mkdir -p "$(dirname $(abspath $target))"
      mv -v "$file" "$target"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

Natürlich funktioniert es immer noch, wenn wir auch keine bestimmten Zielordner haben.

Wenn wir alle Songs in einen Ordner legen wollten, können ./Beethoven/wir dies tun:

Verwendung

sedrename 's|Beethoven - |Beethoven/|g' *.mp3

before:

./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3

after:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

Bonusrunde ...

Verwenden dieses Skripts zum Verschieben von Dateien aus Ordnern in einen einzelnen Ordner:

Angenommen, wir wollten alle übereinstimmenden Dateien sammeln und im aktuellen Ordner ablegen, dann können wir Folgendes tun:

sedrename 's|.*/||' **/*.mp3

before:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

after:

./Beethoven/ # (now empty)
./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

Hinweis zu sed regex-Mustern

In diesem Skript gelten die Regeln für reguläre sed-Muster. Diese Muster sind keine PCRE (Perl Compatible Regular Expressions). Sie hätten die erweiterte Syntax für reguläre Ausdrücke entweder sed -roder sed -E abhängig von Ihrer Plattform verwenden können.

man re_formatEine vollständige Beschreibung der sed-Basis- und erweiterten Regexp-Muster finden Sie in der POSIX-Konformität .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.