#! /usr/bin/perl -w
####################### rename_files_with_dates.pl
### $Id: rename_files_with_dates,v 1.3 2005/05/18 17:09:13 toma Exp toma $
### $Source: /home/cujo/toma/reality/arneberg/digicams/fz20/software/RCS/rename_files_with_dates,v $
### Started: 05/12/2005
### Author:  Thomas R. Arneberg, tom@arneberg.com, http://arneberg.com
#
# This is a Perl program to rename filenames to put the date in them.
# It mimics the default naming convention of my Olympus c2100uz digital
# camera on files produced by my new Panasonic FZ20 camera. It should
# work with files from any camera (you may have to tweak it).
#
#   Example usage:
#     % rename_files_with_dates *.jpg
#
#   Example results:
#       old name:  P1000542.jpg
#       new name:  P4080542.jpg  (if the file timestamp is Apr. 8)
#       new name:  PC250542.jpg  (if the file timestamp is Dec. 25)
#
# On my two-year-old Linux box, this program changes the names
# of 200 files in less than one second!
#
# NOTE: I am sure that there are better ways to write much of this
# code! I also put in some safeguards that you may want to relax 
# (or you may want to add your own additional safeguards).
# I just wanted to hammer something out quickly, and thought 
# I'd share it with others -- take it or leave it.  ;-)
#
# NOTE2: this should work on most operating systems -- AIX, IRIX,
# Solaris, Linux, HP-UX, etc.  I suppose it may need some tweaking 
# to work on Windoze or Macs, though.
#
#    - Tom Arneberg
#      http://arneberg.com/digicams/fz20


use strict;	

my $progname = "rename_files_with_dates";

#######################################################################
### Parse command-line arguments:

my $numargs = $#ARGV + 1;
# printf("  numargs = $numargs\n");
if ( $numargs == 0 ) {
  &USAGE();
}

for (my $arg_index = 0; $arg_index <= $#ARGV; $arg_index++) { 
  my $arg = $ARGV[$arg_index];

  ### User wants help:
  if ( $arg eq "-help" || $arg eq "-h" || $arg eq "help" || $arg eq "h") {
    &print_info();
    exit 1;
  }

}

### All the other args should be filenames:
my @filenames = @ARGV;

#########################################################
####################    MAIN LOOP    ####################
#########################################################

my $filename;
foreach $filename (@filenames) {
  &rename_one_file($filename);
}

exit;

#######################################################################
### Rename one file:
sub rename_one_file {
  my ($oldname) = $_[0];

  if (! -f $oldname) {
    printf("\n### ERROR: can't find old file \"$oldname\"\n\n");
    return;
  }

  if (&filename_is_suspicious) {
    printf("  SKIPPING suspiciously named file: \"$oldname\"\n\n");
    return;
  }

  my $newname = &determine_new_filename($oldname);

  if (-f $newname) {
    printf("\n### ERROR: proposed new filename already exists: \"$newname\"\n");
    printf("    (skipping file \"$oldname\"...)\n\n");
    return;
  }

  printf("  renaming file: \"$oldname\" -> \"$newname\"...\n");
  rename($oldname, $newname);
  
}

#######################################################################
### Determine new name for file:
sub determine_new_filename {
  my ($filename) = $_[0];

  my $datestr = &get_file_date_3dig($filename);

  my @chars = split(//, $filename);
  my $length = $#chars - 3;
  my $rest_of_name = substr($filename,4,$length);
  my $newname = "p" . $datestr . $rest_of_name;

  # printf(" rest_of_name = $rest_of_name\n");
  # printf(" datestr      = $datestr\n");
  # printf(" oldname     = $oldname\n");
  # printf(" newname      = $newname\n");

  return $newname;
}

#######################################################################
### Check to see if the filename looks suspicious:
sub filename_is_suspicious {
  my ($filename) = $_[0];

  my $exp_str = "p10";

  my @letter;	# array for holding characters in filename

  my $first3 = substr($filename,0,3);
  # printf(" first3 = $first3\n");

  if ($first3 eq $exp_str) {
    return 0;
  } else {
    printf("  (first 3 characters are \"$first3\"; expected \"$exp_str\")\n");
    return 1;
  }

}

#######################################################################
### Get the modified date of file and convert to three digits:
sub get_file_date_3dig {
  my ($filename) = $_[0];

  my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);
  my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,
      $mtime,$ctime,$blksize,$blocks);

  ### Extract info about the file:
  ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,
      $mtime,$ctime,$blksize,$blocks) = stat $filename;

  ### Extract info about last-modified time:
  ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($mtime);

  ### Convert date to three digits (with 10=A, 11=B, 12=C):
  $mon++;	# want January = 1, not 0
  if ($mon eq "10") { $mon = "A" };
  if ($mon eq "11") { $mon = "B" };
  if ($mon eq "12") { $mon = "C" };
  my $datestr = sprintf("%s%02d", $mon, $mday);
  return $datestr;
}


#######################################################################
### Print the command-line usage of this program:
sub USAGE {
print<<EOS;

(full path: $0 )

Usage:  $progname  filename(s)

  Example:
     $progname *.jpg

  (use "$progname -help" to get more info)

EOS
  
  exit 1;
}
