Digicam-Bilder mittels EXIF Informationen umbenennen

Projekt: DigiCam Bilder automatisch von der DigiCam holen, umbenennen, richtig drehen und ablegen. Alles mit einem Script.

Jeder kennt den Fall: Man knipst im Urlaub, auf einer Hochzeit oder sonstwo hunderte von Bildern. Möglichst mit mehreren Kameras und Handys. Die dann zu sortieren und zu ordnen kostet Unmengen von Zeit und Nerven. Warum nicht ein Programm schreiben, das die Bilder beim anstecken an den Rechner direkt mit dem Timestamp des Aufnahmezeitpunkts in ein Verzeichnis auf dem Rechner kopiert.
Das

Image::ExifTool

ermöglicht den einfachen Zugriff auf die Headerdaten von diversen Formaten.
Leider verwendet fast jeder Hersteller eigene Tags um das Erstellungsdatum zu Speichern. Manche Hersteller schreiben auch nur ein Modification Date in die Bilder. Beispiele für diese Varianz:

  • CreateDate
  • DateTimeOriginal
  • DateTimeDigitized
  • ModifyDate
  • FileModifyDate

Ein Alptraum und echt nervig. Das Script kümmer sich automatisch um diese Variationen.

Einfach den folgenden Quelltext in eine Datei (zb: dsc_rename6.pl ) einfügen, ausführbar machen.

Der Aufruf des Scripts ist einfach und simpel:

/bin/dsc_rename6.pl
usage1 rename: /bin/dsc_rename6.pl pfad prefix
usage2 rename and move: /bin/dsc_rename6.pl quellpfad zielpfad prefix
example:
/bin/dsc_rename6.pl /daten/DigiCam/neue_Bilder Urlaub
/bin/dsc_rename6.pl /daten/DigiCam/neue_Bilder /daten/DigiCam/Urlaubs_Bilder/ Urlaub

Aktuell werden folgende Dateitypen werden derzeit erkannt und richtig ausgewertet und abgelegt.
*.JPG | *.jpg | *.mov | *.MOV | *.MP4 | *.m4v | *.mp4 | *.MPG | *.mpg | *.MTS | *.mts | *.MOD | *.mod | *.AVI | *.avi | *.3gp | *.3GP | *.CR2 | *.cr2

Das Script:

#!/usr/bin/perl -w

# Projekt: DigiCam Bilder automatisch umbenennen und drehen

# (C) by Hagen Gloetter (at) gmail.com
# started on 05.2012
# latest version 11.2015
###   
# rekursiv durch Verzeichnisse traversieren howto
#http://www.informatik.uni-frankfurt.de/~haase/PerlKurs/perl/perl_file.html#glob

# ExifTool installieren (falls nicht in Distribution enthalten)
# sudo cpan Image::ExifTool

# jhead um die Headerdaten von jpgs auzulesen
# jhead -> http://www.linux-community.de/Internal/Artikel/Print-Artikel/LinuxUser/2005/10/JPEG-Bilder-automatisch-umbenennen-und-verlustlos-bearbeiten/(article_body_offset)/2
# download http://www.sentex.net/~mwandel/jhead/

my $debug = 0; # set to 1-5 for debug output

use strict;
use diagnostics;
use POSIX qw(strftime);
use Image::ExifTool ':Public';
use File::Basename;

my $pfad_quelle = $ARGV[0];
my $para2       = $ARGV[1];
my $para3       = $ARGV[2];
my %bildnummern = ();
my $jhead       = "/usr/bin/jhead"   || die "jhead not found\nplease install\nsudo apt-get install jhead\n";

if ( defined $pfad_quelle and defined $para2 ) {
 print "Parameter Check passed\n;";
}
else {
 print "usage1 rename: $0 pfad prefix\n";
 print "usage2 rename and move: $0 quellpfad zielpfad prefix\n";
 print "example:\n";
 print "$0 /daten/DigiCam/neue_Bilder Urlaub\n";
 print "$0 /daten/DigiCam/neue_Bilder /daten/DigiCam/Urlaubs_Bilder/ Urlaub\n";
 exit;
}

my $pfad_ziel = $para2;
my $prefix    = $para3;

if ( !defined $para3 ) {

 # 2 Parameter Modus
 $prefix    = $para2;
 $pfad_ziel = $pfad_quelle;
}

$pfad_quelle = dirname("$pfad_quelle/.");
$pfad_ziel   = dirname("$pfad_ziel/.");

print "Partameter\n";
print "1:>$pfad_quelle<\n";
print "2:>$pfad_ziel<\n";
print "3:>$prefix<\n";

my @FileArray = ();
push( @FileArray, glob( $pfad_quelle . "/*.JPG" ) );  # Achtung Reihenfolge ist wichtig! 
push( @FileArray, glob( $pfad_quelle . "/*.jpg" ) );  # nicht zusammenfassen
@FileArray = sort(@FileArray);

push( @FileArray, glob( $pfad_quelle . "/*.mov" ) );
push( @FileArray, glob( $pfad_quelle . "/*.MOV" ) );
push( @FileArray, glob( $pfad_quelle . "/*.MP4" ) );
push( @FileArray, glob( $pfad_quelle . "/*.m4v" ) );
push( @FileArray, glob( $pfad_quelle . "/*.mp4" ) );
push( @FileArray, glob( $pfad_quelle . "/*.MPG" ) );
push( @FileArray, glob( $pfad_quelle . "/*.mpg" ) );
push( @FileArray, glob( $pfad_quelle . "/*.MTS" ) );    # Sony HD
push( @FileArray, glob( $pfad_quelle . "/*.mts" ) );
push( @FileArray, glob( $pfad_quelle . "/*.MOD" ) );
push( @FileArray, glob( $pfad_quelle . "/*.mod" ) );
push( @FileArray, glob( $pfad_quelle . "/*.AVI" ) );
push( @FileArray, glob( $pfad_quelle . "/*.avi" ) );
push( @FileArray, glob( $pfad_quelle . "/*.3gp" ) );    # Desire HD
push( @FileArray, glob( $pfad_quelle . "/*.3GP" ) );
push( @FileArray, glob( $pfad_quelle . "/*.CR2" ) );    # RAW
push( @FileArray, glob( $pfad_quelle . "/*.cr2" ) );    # RAW

my $count = @FileArray;
my $i     = 0;
print "count: $count\n";
if ( $count == 0 ) {
 print "Keine Bilder im Ordner $pfad_quelle vohanden\n";
 exit;
}

foreach my $fqfn (@FileArray) {

 my ( $fn, $path, $ext ) = fileparse( $fqfn, qr/\.[^.]*/ );
 my $info       = ImageInfo($fqfn);    # viel einfacher als selber coden
 my %h          = %$info;
 my $CreateDate = "";
 my $Hersteller = "";
 my $Kamera     = "";
 my $FNumber    = "0";
 $i++;

 if ( $debug > 2 ) {
  foreach ( sort keys %h ) {           # ALLE jpeg Parameter ausgeben
   print "$_ : $h{$_}\n";
  }
 }
 $ext = lc($ext);
 if ( defined $h{"$CreateDate"} ) {
  $CreateDate = $h{"$CreateDate"};
 }
 elsif ( defined $h{"DateTimeOriginal"} ) {
  $CreateDate = $h{"DateTimeOriginal"};
 }
 elsif ( defined $h{"DateTimeDigitized"} ) {
  $CreateDate = $h{"DateTimeDigitized"};
 }
 elsif ( defined $h{"ModifyDate"} ) {
  $CreateDate = $h{"ModifyDate"};
 }
 elsif ( defined $h{"FileModifyDate"} ) {
  $CreateDate = $h{"FileModifyDate"};
 }
 $CreateDate =~ s/\+.*//g;    # evtl +x:y Zeitmarken entfernen
 $CreateDate =~ s/:/-/g;
 $CreateDate =~ s/\s+/_/g;

 if ( defined $h{"FileName"} ) {
  $_ = $h{"FileName"};
  m/(\d+)\./; # Annahme: Es gibt keine Filenamen mit Punkten zwischen den Zahlen
  $FNumber = $1 || 0;
 }
 if ( $FNumber == 0 ) {
  $_ = $fn;
  m/(\d+)\./;
  $FNumber = $1 || 0;
 }
 if ( $FNumber == 0 and defined $h{"FNumber"} )
 {            # in dem Tag steht bei den meisten Kameras Mist drin
  $FNumber = $h{"FNumber"};
 }

 if ( defined $h{"Make"} ) {
  $Hersteller = $h{"Make"};
  $Hersteller = "" if ( $Hersteller =~ /Canon/i );    # Canon Dopplung entfernen
 }
 if ( defined $h{"Model"} ) {
  $Kamera = $h{"Model"};
 }

 my $new_fn = "$CreateDate $prefix $Hersteller $Kamera $FNumber";
 $new_fn =~ s/\s+/-/g;
 $new_fn =~ s/,/-/g;
 $new_fn =~ s/-+/-/g;

 print "$i/$count ";
 if ( $fqfn =~ /$pfad_ziel\/$new_fn$ext/ ) {
  print "skipping: Name OK -> $fqfn\n";
 }
 else {
  my $pfad_print = $pfad_quelle;
  $pfad_print =~ s/$pfad_ziel//;
  print "rename $fn -> $pfad_print$new_fn$ext";
  print "rename $fqfn -> $pfad_ziel/$new_fn$ext" if ( $debug > 2 );
  if ( rename( "$fqfn", "$pfad_ziel/$new_fn$ext" ) ) {
   my $ret = "";
   $ret = `$jhead -autorot $pfad_ziel/$new_fn$ext` if ( $ext =~ /jpg/i );
   print " rotated" if ( $ret =~ /Modified:/ );
   print " -> ok\n";
  }
  else {
   print " -> error: $!\n";
  }
 }

}

 

0 Kommentare

Hinterlasse einen Kommentar

An der Diskussion beteiligen?
Hinterlasse uns deinen Kommentar!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert