Wie kann ich Fotos angesichts der EXIF-Daten umbenennen?


14

Angenommen, ich habe eine Reihe von Fotos, alle mit korrekten EXIF-Informationen, und die Fotos werden nach dem Zufallsprinzip benannt (aufgrund eines Problems, das ich hatte). Ich habe ein kleines Programm aufgerufen, jheaddas mir die folgende Ausgabe gibt:

$ jhead IMG_9563.JPG

File name    : IMG_9563.JPG
File size    : 638908 bytes
File date    : 2011:02:03 20:25:09
Camera make  : Canon
Camera model : Canon PowerShot SX210 IS
Date/Time    : 2011:02:03 20:20:24
Resolution   : 1500 x 2000
Flash used   : Yes (manual)
Focal length :  5.0mm  (35mm equivalent: 29mm)
CCD width    : 6.17mm
Exposure time: 0.0080 s  (1/125)
Aperture     : f/3.1
Focus dist.  : 0.29m
ISO equiv.   : 125
Exposure bias: -1.67
Whitebalance : Manual
Light Source : Daylight
Metering Mode: pattern
Exposure Mode: Manual

Jetzt muss ich alle Fotos im Ordner im nächsten Format umbenennen:

001.JPG
002.JPG
003.JPG
...

Wobei die kleinere Zahl das ältere Bild und das Maximum das neuere ist.

Ich schreibe nicht so gut, deshalb bitte ich um Hilfe.

Ich denke, ein Bash-Skript reicht aus, aber wenn Sie sich wohler fühlen, können Sie ein Python-Skript schreiben.

Ich dachte in etwas wie:

$ mv IMG_9563.JPG `jhead IMG_9563.JPG | grep date`

aber ich weiß nicht, wie ich das für alle Dateien auf einmal machen soll.


Ich verstehe den Neben- / Höchstsatz und das vorstehende Beispiel nicht. Könnten Sie das klären?
Maxschlepzig

Dieser kleinere / maximale Dateiname ist eine Stufe höher. Denn sobald ich die Dateien so benannt habe, dass sie älter und neuer sind, kann ich sie mit einem anderen Programm leicht in 001.jpg, 002.jpg usw. umbenennen, obwohl es besser wäre, dies mit einem anderen Skript zu tun.
Tomas

Die "Umbenennungstabelle" wäre ls *.JPG | wc > renameUnd dann müsste ich ein Skript verwenden, das in XXX.JPG umbenannt wird
Tomas

Tut wcmir leid, ich habe vergessen, den mit Namen zu bestellen.
Tomas

Der Befehl lautet sort.
Tomas

Antworten:


10

Sie können für alle Dateien eine for-Schleife verwenden (in der Shell / in einem Shell-Skript):

for i in *.JPG; do
  j=`jhead "$i" | grep date | sed 's/^File date[^:]\+: \(.\+\)$/\1/'`.jpg
  echo mv -i "$i" "$j"
done

Dies ist nur eine sehr grundlegende Übersicht. Löschen echoSie, wenn Sie überprüft haben, dass alles wie erwartet funktioniert.


Vielen Dank. Nun, grep, gib mir File date : 2011:02:03 20:25:09. Wie kann ich nur die zweite Spalte filtern?
Tomas

Daher benenne ich die Datei nur um als 20:25:09
Tomas

@Tomas, hat die Antwort aktualisiert - wenn Sie wirklich nur die Zeit wollen (was ist dann mit Kollisionen?), Müssen Sie natürlich den regulären Ausdruck ändern.
maxschlepzig

j=`jhead "$i" | grep date | sed 's/.* //'`.jpgstattdessen?
Frabjous

@maxshlepzig: Danke, du hast ein 'vorheriges `` .jpg`` verpasst
Tomas

28

Gerade herausgefunden, hier , dass jhead alles für Sie tun kann! :)

jhead -autorot -nf%Y-%m-%d_%H-%M-%S *.jpg

7
Ja! Aber seien Sie vorsichtig mit dieser speziellen Format-Zeichenkette, denn sie gibt zwei Dateien, die in derselben Sekunde aufgenommen wurden, den gleichen Namen. %i(oder %03ispeziell) wird eine Sequenznummer geben, wie in der ursprünglichen Frage angefordert. Beides zu kombinieren könnte keine schlechte Idee sein.
Mattdm

Nur um auf den Kommentar von mattdm zu antworten - das '' jhead '' Handbuch schlägt vor, dass Duplikate (identischer Zeitstempel) automatisch mit einer zusätzlichen Zahl oder einem Buchstaben (1,2,3 oder a, b, c usw.) versehen werden.
John U

0

Wenn jemand eine komplexere Umbenennung benötigt, um beispielsweise wichtige Belichtungswerte in den Dateinamen aufzunehmen, ist hier mein kleines Skript. Es benennt JPEG - Dateien zu etwas wie folgt aus : NightSky_2014.08.27_22.30.05_NX20_F2.8_f20.0mm_20s_ISO800.jpg.

#!/bin/bash

for s in *.jpg *.JPG
do
 echo $s
 x=`jhead "$s" | \
 awk 'BEGIN { cmt=""; }
/Camera model/   { c=$4$5$6;} 
/Exposure time:/ { e=$3; 
                   if (e==int(e)) e=int(e); 
                   if (e<1) {e=int(0.5+1/e); e="1T" e "s";} else { e=e "s"; } 
                 }
/ISO equiv./     { iso="ISO" $4; } 
/Focal length/   { f="f" $4; } 
/Date.Time /     { d=$3 "_" $4; gsub(":",".",d); }
/Aperture /      { ap=$3; gsub("f/","F",ap); } 
/Comment  /      { cmt=$3 "_"; }
END { print cmt d "_" c "_" ap "_" f "_" e "_" iso ".jpg"; }'`

 echo mv $s $x
 mv $s $x
 echo =====
done

0

Ich mochte den Code von maxschlepzig, hatte aber trotzdem Probleme mit der Ausgabe.

Das Problem war das Leerzeichen im resultierenden Dateinamen (zwischen der Datums- und Zeitzeichenfolge). Dies ist für Benutzer einer grafischen Benutzeroberfläche zwar trivial, erschwert jedoch die Dateiverwaltung über die Befehlszeile.

Hier wurde der Befehl 'sed' zu Gunsten des vorherigen monolithischen Arguments in vier separate 'sed'-Operationen geändert. Das Folgende ändert auch die Datei auf normale 644-Berechtigungen.

for i in *.JPG ; do
  chmod 644 $i
  j=`jhead "$i" | grep ^Date/Time | sed -e 's/^Date\/Time[ ]\+: //;s/:/-/g;s/ /_/g':/-/g;s/ /_/g'`.jpg
  echo mv -i "$i" "$j"
  # mv -i "$i" "$j"
done

2
Willkommen bei Stack Exchange. (1) Ich verstehe sedziemlich gut, also verstehe ich im Grunde, was Sie versuchen zu tun. Unser Ziel bei Stack Exchange ist es jedoch nicht, Fischbrötchen zu verteilen oder Tausende von einmaligen Lösungen für trivial unterschiedliche Fragen zu schreiben. Unser Ziel ist es, den Menschen das Fischen beizubringen (dh den Menschen, einschließlich des aktuellen Fragestellers und zukünftiger Leser, beizubringen, wie sie ihre eigenen Probleme lösen können). Zu diesem Zweck wäre Ihre Antwort besser, wenn Sie erklären würden, was Sie anstreben. (Bitte nicht reagieren in den Kommentaren, bearbeiten Sie Ihre Antwort es klarer zu machen.) ... (Fortsetzung)
G-Man sagt "wieder einzusetzen Monica

(Fortsetzung)… (2) Ihr Befehl schlägt fehl, weil die Anführungszeichen nicht ausgeglichen sind. Bitte posten Sie keinen ungetesteten Code.
G-Man sagt, dass Monica

0

Da es einfacher ist, mit (imho) umzugehen, habe ich mir ein Ruby-Skript geschrieben:

require 'fileutils'

ARGV.each { |file|
  if File.exist?(file) && !File.directory?(file)
    exif = `exiftool "#{file}" | grep -E "(Error|Create Date)"`
    if exif.strip.size > 0
      exif = exif.split("\n")[0].split(/\s+/)
      if exif[0] != "Error"
        # Change the target format here
        filename = exif[3].gsub(":", "-") + " " + 
                   exif[4].gsub(":", ".") + 
                   File.extname(file)
        if filename != file && !File.exist?(filename)
          FileUtils::mv(file, File.dirname(file) + "/" + filename)
        end
      end
    end
  end
}

Was macht das?

  1. Durchläuft alle Dateien, die als Parameter übergeben wurden (z *.JPG. B. ).

    Ich habe überprüft, ob RAW-Dateien und -Videos korrekt verarbeitet werden. Es sollte funktionieren, mit allem, was exiftoolman anfangen kann.

  2. Tut nichts wenn eine Datei

    • ist nicht vorhanden,
    • ist ein Verzeichnis,
    • hat kein EXIF-Datum, oder
    • exiftool meldet einen Fehler oder
    • Eine Datei mit dem Zieldateinamen ist bereits vorhanden.

Das macht es ziemlich robust. Insbesondere können keine Dateien (still) verschwinden, wie dies bei einigen anderen Antworten der Fall ist.


0

exiv2 wäre eine alternative zum manipulieren, die eine sehr einfache syntax erlaubt:

exiv2 ist ein Programm zum Lesen und Schreiben von Exif-, IPTC-, XMP-Metadaten und Bildkommentaren und kann viele Hersteller-Makernote-Tags lesen. Das Programm konvertiert optional zwischen Exif-Tags, XMP-Eigenschaften und IPTC-Datensätzen

Das würde also alle JPEGs im aktuellen Ordner umbenennen:

for i in *.JPG; do exiv2 -v -r '%Y%m%d.%H%M%S.:basename:' rename "$i"; done

Wenn Sie auch Geoinformationen hinzufügen möchten, können Sie Folgendes verwenden exivtool:

exiftool '-filename<${gpslatitude;} ${gpslongitude} ${datetimeoriginal}' -d "%Y-%m-%d %H.%M.%S%%-c.%%e" *.JPG

0

Ich mag die Lösung von @ Kevin, da ich auch den ursprünglichen Namen beibehalten wollte (um Probleme mit Bildern zu vermeiden, die in derselben Sekunde aufgenommen wurden). Hier ist meine Lösung:

for i in *.JPG; do jhead -nf%Y%m%d_%H%M%S_"$(basename "$i" .JPG)" "$i" ; done

0

Erstes Posting von Neuling ... Erstes Bash-Skript ... Ich mochte die Libor / HalosGhost-Lösung oben, da sie beim Umbenennen weitere Details enthielt. Nach dem Testen würden doppelte Dateinamen jedoch Dateien verlieren. Daher habe ich ein Counter-Tag am Ende des Dateinamens hinzugefügt, um eine einfache Referenz und Kollisionsverhütung zu gewährleisten. Ich bin mir sicher, dass jemand hier dies verbessern kann, aber ich dachte, es könnte helfen.

Ich entschuldige mich für den Code. Ich habe Probleme mit der Benutzeroberfläche, aber wenn mich jemand auf die richtige Vorgehensweise hinweisen könnte, wäre das großartig.

#!/bin/bash

y=1
for s in *.jpg *.JPG
do
 echo $s
 x=`jhead "$s" | \
 awk 'BEGIN { cmt=""; }
/Camera model/   { c=$4$5$6;}
/Exposure time:/ { e=$3;
                   if (e==int(e)) e=int(e);
                   if (e<1) {e=int(0.5+1/e); e="1T" e "s";} else { e=e "s"; }
                 }
/ISO equiv./     { iso="ISO" $4; }
/Focal length/   { f="f" $4; }
/Date.Time /     { d=$3 "_" $4; gsub(":","",d); }
/Aperture /      { ap=$3; gsub("f/","F",ap); }
/Comment  /      { cmt=$3 "_"; }
END { print cmt d "_" c "_" ap "_" f "_" e "_" iso "_" ; }'`

 echo mv $s "$x${y}.jpg"
 mv $s "$x${y}.jpg"
 y=$((y+1))
 echo =====
done

Danke Stephen für die Bearbeitung. Der Versuch zu lernen
jgroezin
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.