Tuesday, 26 June 2012

Watch your P's and p's

I have photos and duplicates of photos everywhere on my PC, laptop etc. and have been trying to find a piece of software to organise my digital photos for a long time, and have never found exactly what I was looking for, so I have attempted to come up with a solution myself.


I was careful when renaming files according to my own predefined convention based on date taken. I use XnView to extract the relevant EXIF metadata and rename the files as follows:
YYYY-MM-DD HH-MM-SS {Camera Model}
This is working perfectly as it has generated a unique filename for all of my photos (I don't tend to do bursts which would all have the same timestamp) and I have been able to separate the photos into a directory structure base on YYYY/MM using the following simple shell script:


#!/bin/bash

# Sorts the files in the current folder to relevant folder ../YYYY/MM based on each file name

for file in *
do
 Year=$(echo $file | cut -c-4)
 Month=$(echo $file | cut -c6-7)

 $(mv -n  "$file" ../$Year/$Month/)
done


My problem is I haven't been so careful about the file extensions in XnView.  There is an option to have the file extension convert to UPPERCASE or lowercase - I used have both unfortunately.  The problem occurs when I have duplicates of photos which have the same name, but a different extension case - and Linux is case sensitive.  I end up with duplicates of the same photo simply because the extension  is different.


Now I am trying to write a script to untangle the mess I have created...


#!/bin/bash

#######################################################################
######          Converts a file extension to lowercase           ######
#######################################################################

# Counter variables
renamed=0 # this counts the number of files which were renamed
skipped=0 # this counts the number of files which were not renamed

# Loop thru the files in the current directory
for file in *
do
 # Extract the filename and extension from each file
 filename=$(echo "${file%.*}")
 EXT=$(echo "${file##*.}")

 # Convert the extension to lowercase
 ext=$(echo "${EXT,,}")

 # Proposed filename and extension
 newFile=$(echo "${filename}.${ext}")

 # Rename the file only if the extension was NOT already in lowercase
 if [ $ext != $EXT ];
 then
  # Check if the proposed new filename already exists
  if [ -e $newFile ];
  then
   # Add a duplicate identifier to end of filename
   newFile=$(echo "${filename}_01.${ext}")
  fi
 
  # Rename the file
  echo "Renaming file: $file >>>>> $newFile"
  $(mv '$file' '$newFile')
  # Increment renamed files counter
  renamed=$((renamed+1))
 else
  echo "Skipping file: $filename.$ext"
  # Increment skipped files counter
  skipped=$((skipped+1))
 fi
done

# Output summary information
echo "There were $renamed files renamed and $skipped files skipped"
It's not quite there yet; I need to get it to work recursively down a directory structure eventually, but first I need to make sure it works. Anyone know why I am getting a too many arguments error for the file exists test on line 28??? Help???

1 comment:

  1. Wouldn't you know it... the syntax was okay, but the file names contained spaces and therefore appeared as separate parameters to the file exists contitional. I changed the following line in the script
    if [ -e $newFile ];
    to
    if [ -e "$newFile" ];
    which solved my problem

    ReplyDelete