Bulk-Umbenennung von Dateien

25

Ich habe eine Reihe von Dateien:

10.3.100.179_01_20161018_230014_5335.jpg
10.3.100.179_01_20161018_231514_0814.jpg
10.3.100.179_01_20161018_233014_5706.jpg
10.3.100.179_01_20161018_234514_0896.jpg
10.3.100.179_01_20161018_230114_5395.jpg
10.3.100.179_01_20161018_231614_1145.jpg
10.3.100.179_01_20161018_233114_6047.jpg
10.3.100.179_01_20161018_234614_0547.jpg
10.3.100.179_01_20161018_230114_5492.jpg
10.3.100.179_01_20161018_231614_1264.jpg
10.3.100.179_01_20161018_233114_6146.jpg
10.3.100.179_01_20161018_234614_0658.jpg
10.3.100.179_01_20161018_230214_5630.jpg
10.3.100.179_01_20161018_231714_7135.jpg

Ich möchte mit diesem Format umbenennen:

10.4.100.135_01_20161013131108389_TIMING.jpg
10.4.100.135_01_20161013131111390_TIMING.jpg
10.4.100.135_01_20161013131114401_TIMING.jpg
10.4.100.135_01_20161013131117431_TIMING.jpg
10.4.100.135_01_20161013131120418_TIMING.jpg
10.4.100.135_01_20161013131123461_TIMING.jpg
10.4.100.135_01_20161013131126511_TIMING.jpg

Es muss den _In-Zeitstempel entfernen und den hinzufügen _TIMING.

Jojo Mendoza
quelle
5
Bitte verwenden Sie in Ihren Fragen konsistente Beispiele. Es sieht aus wie Sie ersetzen möchten 10.3.100.179mit 10.4.100.135. Wollen Sie das oder wollen Sie nur das _TIMINGund das _aus der Zeit entfernen ?
Terdon
3
Ein guter Zeitpunkt, um die Leute daran zu erinnern, dass es einen ISO8601-Standard für Datumsangaben gibt (der sowohl für Dateinamen als auch für Protokolleinträge funktioniert) ^^ Vielleicht sollten Sie die Umbenennung in: JJJJ-MM-TTThh: mm: ss.mmm (z. B. : Ihre erste Datei würde: 10.4.100.135_01_2016-10-13T13:11:08.389_TIMING.jpg(und "TIMING" könnte dann sogar entfernt werden, da es jetzt eindeutig wie ein Datum und eine Stunde (und Millisekunden) aussieht, insbesondere wenn der Standard weiter verbreitet wird. Das T ist Teil des Standards und ich wuchs es zu mögen (und
Olivier Dulac
@OlivierDulac Ich würde nicht empfehlen, :in einem Dateinamen zu verwenden. Ich glaube, Windows unterstützt das nicht.
Justin
@ Justin guter Punkt. Der Standard empfiehlt, es für Dateinamen zu löschen. Ich gab die In-File-Version
Olivier Dulac

Antworten:

38

Installieren renameutilsund qmvmit Ihrem bevorzugten Texteditor verwenden.

qmvLädt alle Namen in Ihren Editor und beim Speichern und Schließen werden die Änderungen auf die eigentlichen Dateien angewendet. Wenn die Änderungen inkonsistent sind (z. B. wenn zwei Dateien denselben Namen haben), wird der Vorgang abgebrochen, ohne dass etwas berührt wird. Zirkuläre Umbenennungen werden ebenfalls korrekt behandelt.

Normalerweise mache ich:

$ qmv -f do

Damit wird nur eine Spalte mit Namen angezeigt (do: destination-only). So sieht es aus:

qmw

Wenn Sie es mit den mehreren Cursorn von SublimeText, Atom oder Visual Studio Code kombinieren, ist es ein sehr nützliches und leistungsstarkes Werkzeug für die Massenumbenennung. Zum Beispiel würden Sie für Atom tun EDITOR="atom -w" qmv -f do.

ateijelo
quelle
1
Willkommen bei askUbuntu! Das ist so cool!
αғsнιη
Signiert es nur um +! es. ;)
J. Allan
2
Wow, schönes Tool und schöne GIF-Animation. Tolle erste Antwort, sei willkommen! :)
Byte Commander
1
Danke @KasiyA für das Einfügen des Bildes und danke allen anderen für die positiven Kommentare.
Ateijelo
1
@kasperd Ja, es wird gewarnt, dass der Umbenennungsplan Fehler enthält, und eine interaktive Konsole geöffnet, in der weitere Aktionen ausgeführt werden können.
Ateijelo
27

Verwenden Sie rename...

rename -n 's/^([0-9]+\.[0-9]\.[0-9]+\.[0-9]+_[0-9]+_)([0-9]+)_([0-9]+)_([0-9]+)\.jpg/$1$2$3$4_TIMING\.jpg/' *

Mit -ndiesem Befehl wird ausgegeben, was zu tun ist, ohne Änderungen vorzunehmen:

rename(10.3.100.179_01_20161018_230014_5335.jpg, 10.3.100.179_01_201610182300145335_TIMING.jpg)
rename(10.3.100.179_01_20161018_231514_0814.jpg, 10.3.100.179_01_201610182315140814_TIMING.jpg)
rename(10.3.100.179_01_20161018_233014_5706.jpg, 10.3.100.179_01_201610182330145706_TIMING.jpg)
rename(10.3.100.179_01_20161018_234514_0896.jpg, 10.3.100.179_01_201610182345140896_TIMING.jpg)

Wenn es richtig aussieht, entfernen Sie die -n

$ rename 's/^([0-9]+\.[0-9]\.[0-9]+\.[0-9]+_[0-9]+_)([0-9]+)_([0-9]+)_([0-9]+)\.jpg/$1$2$3$4_TIMING\.jpg/' *
$ ls
10.3.100.179_01_201610182300145335_TIMING.jpg  10.3.100.179_01_201610182330145706_TIMING.jpg
10.3.100.179_01_201610182315140814_TIMING.jpg  10.3.100.179_01_201610182345140896_TIMING.jpg

Erklären ...

  • s/something/something_else/ Suchen und Ersetzen
  • ^ der Beginn des Namens (Verankerung)
  • [0-9] irgendeine Nummer
  • + ein oder mehrere der vorhergehenden Zeichen
  • \.wörtlich .(ohne dass \dies einem Zeichen entspricht)
  • () um diesen Teil zu behalten
  • $1$2$3$3 zurück Verweise auf die Dinge früher abgestimmt und gehalten ()

Hinweis: *Am Ende des Befehls werden alle sichtbaren Dateien im aktuellen Verzeichnis abgeglichen. Verwenden Sie gegebenenfalls einen geeigneteren Glob.

Zanna
quelle
2
In einigen Distributionen ist dieser Befehl verfügbar als prename(p für Perl, da das erste Argument ein Perl-Ausdruck ist)
Peter Cordes
12

mmv kann es wie folgt machen:

mmv '*_*_*_*_*.jpg' '#1_#2_#3#4#5_TIMING.jpg'

10.3.100.179_01_20161018_230014_5335.jpg 10.3.100.179_01_201610182300145335_TIMING.jpg

# 1, # 2, # 3, ... verweist hier jeweils auf das passende '*'.

Es ist noch kürzer mit:

mmv '*_*_*.jpg' '#1#2#3_TIMING.jpg'
αғsнιη
quelle
9

Ein anderer renameAnsatz:

$ rename -n 's/(.*)_(.*)_(.*)\./$1$2$3_TIMING./' *
10.3.100.179_01_20161018_230014_5335.jpg -> 10.3.100.179_01_201610182300145335_TIMING.jpg
10.3.100.179_01_20161018_230114_5395.jpg -> 10.3.100.179_01_201610182301145395_TIMING.jpg
10.3.100.179_01_20161018_230114_5492.jpg -> 10.3.100.179_01_201610182301145492_TIMING.jpg
10.3.100.179_01_20161018_230214_5630.jpg -> 10.3.100.179_01_201610182302145630_TIMING.jpg
10.3.100.179_01_20161018_231514_0814.jpg -> 10.3.100.179_01_201610182315140814_TIMING.jpg
10.3.100.179_01_20161018_231614_1145.jpg -> 10.3.100.179_01_201610182316141145_TIMING.jpg
10.3.100.179_01_20161018_231614_1264.jpg -> 10.3.100.179_01_201610182316141264_TIMING.jpg
10.3.100.179_01_20161018_231714_7135.jpg -> 10.3.100.179_01_201610182317147135_TIMING.jpg
10.3.100.179_01_20161018_233014_5706.jpg -> 10.3.100.179_01_201610182330145706_TIMING.jpg
10.3.100.179_01_20161018_233114_6047.jpg -> 10.3.100.179_01_201610182331146047_TIMING.jpg
10.3.100.179_01_20161018_233114_6146.jpg -> 10.3.100.179_01_201610182331146146_TIMING.jpg
10.3.100.179_01_20161018_234514_0896.jpg -> 10.3.100.179_01_201610182345140896_TIMING.jpg
10.3.100.179_01_20161018_234614_0547.jpg -> 10.3.100.179_01_201610182346140547_TIMING.jpg
10.3.100.179_01_20161018_234614_0658.jpg -> 10.3.100.179_01_201610182346140658_TIMING.jpg

Wenn das so zu funktionieren scheint, wie Sie es möchten, entfernen Sie die -n.

terdon
quelle
5

Sie können auch Folgendes verwenden. Erstellen Sie zuerst eine Sicherungskopie Ihrer Dateien und versuchen Sie Folgendes:

find . -name "*.jpg" -type f -print0| while read -d $'\0' file
do
    #extension="${file##*.}"
    newfilename=$(echo "${file%.*}" | sed 's/\(.*\)_\(.*\)_/\1\2/')
    mv "$file" "$newfilename""_TIMING.jpg"
done

sed 's/\(.*\)_\(.*\)_/\1\2/')löscht die _Zeichen im Zeitstempel.

Beispielsweise:

user@host$ ls -lart
total 8
drwxrwxr-x 6 user user 4096 Oct 21 10:21 ..
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_230014_5335.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_231514_0814.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_233014_5706.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_234514_0896.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_230114_5395.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_231614_1145.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_233114_6047.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_234614_0547.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_230114_5492.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_231614_1264.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_233114_6146.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_234614_0658.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_230214_5630.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_20161018_231714_7135.jpg
drwxrwxr-x 2 user user 4096 Oct 21 10:30 .

user@host$ find . -name "*.jpg" -type f -print0 | while read -d $'\0' file
> do
>  newfilename=$(echo "${file%.*}" | sed 's/\(.*\)_\(.*\)_/\1\2/')
>  mv $file $newfilename"_TIMING.jpg"
> done

10:35:20 t $ ls -lart
total 8
drwxrwxr-x 6 user user 4096 Oct 21 10:21 ..
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182300145335_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182315140814_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182330145706_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182345140896_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182301145395_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182316141145_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182331146047_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182346140547_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182301145492_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182316141264_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182331146146_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182346140658_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182302145630_TIMING.jpg
-rw-rw-r-- 1 user user    0 Oct 21 10:30 10.3.100.179_01_201610182317147135_TIMING.jpg
drwxrwxr-x 2 user user 4096 Oct 21 10:35 .
Mustafa DOGRU
quelle
1
Das ist die beste Lösung. Natürlich ist Zannas Soultion perfekt für ein paar Dateien, aber da das Globbing von der Shell ausgeführt wird, schlägt ihre Lösung möglicherweise bei einer großen Anzahl von Dateien fehl (Befehlszeichenfolge zu lang).
rexkogitans
@rexkogitans: Wenn Sie auf einem modernen Linux-System (dh einer beliebigen Ubuntu-Version) arbeiten, ist die Befehlszeilenlänge auf mehrere Megabyte begrenzt. Und wenn es ein Problem ist, können Sie find -maxdepth 1 -exec rename ... {} +die Auflistung des aktuellen Verzeichnisses in der Befehlszeile von Rename stapeln. (Hinzufügen -name *.jpgoder was auch immer Sie wollen). Das wird viel schneller ausgeführt als eine Shell-Schleife, die forks + execs sedund mvfür jeden Dateinamen ausführt , anstatt nur einen Systemaufruf umzubenennen. (Sie könnten sedBashs eingebautes Regex-Zeug loswerden , aber das Gabeln mvist immer noch langsam.)
Peter Cordes
2

Sie sind wahrscheinlich fertig, aber hier ist eine (einfache) bashLösung:
Ist "simple ... bash solution" ein Oxymoron?

#!/bin/bash

#loop through all files ending in .jpg
for f in *.jpg;
do

    #cut out everything to the timestamp
    firsthalf=${f%_*_*_*}

    #get from the timestamp on
    lasthalf=${f#*_*_}

    #remove (all) underscores from timestamp
    #note the 2 forward slashes...
    lasthalf=${lasthalf//_/}

    #get our extension
    ext=${lasthalf##*.}

    #now we can remove the extension
    lasthalf=${lasthalf%.*}

    #rename the file
    #change `mv` to `echo` if you want to do a trial run first...
    mv "$f" "${firsthalf}_${lasthalf}_TIMING.${ext}"

done;

PS: Die Logik in der Schleife wurde mit einem Ihrer Beispieldateinamen getestet. Es ging vorbei.

J. Allan
quelle
1
Wahrscheinlich ist es besser, einen Bash-Regex mit [[ $f ~= (.*)_(.*)_(.*)_(.*)\.jpg ]]; newname=${BASH_REMATCH[1]${BASH_REMATCH:2:4}TIMING.jpgoder so zu verwenden. (Völlig ungetestet und wahrscheinlich falsch, aber die allgemeine Idee ist, dass Erfassungsgruppen in das BASH_REMATCH-Array aufgenommen werden.)
Peter Cordes,
@ PeterCordes: Das ist ein guter Punkt! Ich habe noch nie ( bash) Capturing-Gruppen verwendet, und um ganz ehrlich zu sein, ist bash nicht die erste Sprache, mit der ich sie ausprobieren würde. (Ich denke, es bashist eine hässliche Sprache.) Trotzdem ist es eine gute Lösung und hat mir etwas so Gutes beigebracht.
J. Allan
Ja, der Hauptgrund, um so viel Text in reiner Bash zu verarbeiten, ist das Schreiben von Funktionen zur Vervollständigung von Tabulatoren, die schnell sein sollten. Es bringt eine ganz neue Bedeutung in die Phrase "hässlicher Code" ...
Peter Cordes
@PeterCordes: Ich verstehe, obwohl ich diesen Code nicht für "hässlich" halte. Es ist vielleicht nicht die 2-Zeilen-Lösung, die Sie gegeben haben, aber für mich ist es nicht schwer zu lesen. und es ist gut kommentiert ...
J. Allan
Ich habe darüber gesprochen, dass der Bash-Completion-Code im Allgemeinen hässlich (oder zumindest schwer zu lesen) ist. Eigentlich ist es nicht wirklich hässlich, nur ein wenig nervenaufreibend (z. B. das Übergeben von Argumenten per ref in bash, indem ein Variablenname übergeben wird und der Angerufene printf -v "$3" ...die Variable setzt, in der der Name enthalten ist $3.) zusammen ist ziemlich schwer zu verfolgen / zu debuggen, zumindest habe ich es so gefunden, als ich versucht habe, es aufzuräumen / Fehler zu beheben. Siehe den Code auf Github
Peter Cordes
1

Wenn Sie GUI verwenden könnten, würde ich pyRenamer empfehlen .

Es ist in den meisten Distributionen vorhanden, zB in Ubuntu:

sudo apt-get install pyrenamer

Es kann alles, was Sie wollen und mehr.

  • Es kann Muster verwenden, Text hinzufügen oder unterdrücken.
  • Es kann auf die EXIF-Daten zugreifen, wenn Fotos umbenannt werden, sodass Sie Muster basierend auf Datum / Uhrzeit usw. erstellen können.
  • Kann beim Umbenennen von Musikdateien einige Metadaten verwenden.
  • Darüber hinaus verfügt es über eine Vorschau , die verhindern kann, dass einige Fehler nur schwer wiederhergestellt werden können.
jrierab
quelle
An den Downvoter ... Möchtest du erklären, warum? OP hat nicht angegeben, ob GUI eine Option ist oder nicht. Ich sehe, dass die meisten Antworten auf die Konsolen- / Skriptweise gehen, aber viele Benutzer werden eine GUI-Lösung zu schätzen wissen. Oder vielleicht hat pyRenamer einen Fehler, den ich nicht kenne. In jedem Fall möchte ich die Gründe für Abstimmungen kennen.
Jrierab
Könnte ich auch Thunar Bulk Renamer für einen bissigen interaktiven GUI-Ansatz vorschlagen.
Tony Martin
@ TonyMartin Dies sollte Kommentar unter Frage sein, dies hat nichts mit der Antwort zu tun
Sergiy Kolodyazhnyy
0

Hier ist Ihre RAW - built-in find + xargs+ sed+ mvoneliner (Liebe oneliners):

find . -name "*.jpg" -print0 | sort -z | xargs -0 sh -c 'for filename; do mv "$filename" $(echo "${filename}" | sed "s/\([0-9]\{8\}\)_\([0-9]\{6\}\)_\([0-9]\{4\}\)/\1\2\3_TIMING/g"); done' sh

Erläuterung:

  • find . -name "*.jpg" | sort | xargs sh -c <command> sh : liste alle JPEGs im aktuellen Verzeichnis auf und führe dann für jedes einen Shell-Befehl aus (die Sortierung ist natürlich optional, aber halte die Dinge ein wenig sauberer, wenn du dich irgendwo anmeldest)

  • -print0, -z, -0: Es ist gute Gewohnheit zu trennen Elemente mit binären , 0wenn Dateinamen Zeichenüber Probleme zu vermeiden , die mit in-the-Middle - weiß-Räumen (nicht Ihr Fall though)

  • mv "$filename" $(echo "${filename}" | sed "s/\([0-9]\{8\}\)_\([0-9]\{6\}\)_\([0-9]\{4\}\)/\1\2\3_TIMING/g");: (Schrägstriche in dem sed‚s regex nicht helfen , die Lesbarkeit, aber es ist einfach) jede Datei umbenennen , indem Sie die Unterstrich-separeted Folge von 8 + 6 + 4 Stellen mit ihrer zusammenhängenden Verkettung und diese ersetzt _TIMINGSache ( \iein Rückreferenzierung zu der ist i- Regex-Gruppe).


Refs: Xargs - Mann sed

Campa
quelle