Monday, December 7, 2020

Bash: Script to archive files into YYYY/MM based on creation date

 I had over 10 years of photos that I wanted to organize by YYYY/MM.  Created this Bash script to do it.

#!/bin/sh
#script:       archiver.sh
#
#

sourceDir="/f/from_kims_ext/"
#sourceDir="/f/test/"
archiveDir="/f/image_archive/"
ARCHIVEFILE="/f/move_archive.txt"

function getfilelist {
`ls -Rp $sourceDir | awk '
/:$/&&f{s=$0;f=0}
/:$/&&!f{sub(/:$/,"");s=$0;f=1;next}
NF&&f{ print s"/"$0 }' | sed "/\/$/d" > $ARCHIVEFILE`
}

function parsefilename {
  sourcefilename=`basename $1`
  extension="${sourcefilename##*.}"
  filename="${sourcefilename%.*}"
}

function updatefilename {
  typeset counter
  counter=0
  
  #check if ok to use original filename
  updatecheck="$archiveDir$datepath/$filename.$extension"
  echo "checking if target $updatecheck exists"
 # if [[ -f $updatecheck ]]; then
   if [ ! -f ${updatecheck} ]; then
    echo "$updatecheck does not exist"
    return
  else
    echo "$updatecheck exists"
  fi

  while [[ $counter -lt 200 ]]
  do
    counter=$((counter+1))
    updatecheckinc="$archiveDir$datepath/$filename"
    updatecheckinc+="_"
    updatecheckinc+="$counter.$extension"
    echo "checking for new $updatecheckinc"
    if [[ ! -f "${updatecheckinc}" ]]; then
      break
    fi
  done
 # changing name because it already exists, so increment to new file name
  filename+="_"
  filename+="$counter"
  echo "updating filename to $filename"
  return
}

set -u
#LOG_TIME=`date |cut -c12-13,15-16,21-23| sed s/" "//g`
LOG_TIME=`date`
 thisyear=`date +"%Y"`
 thismonth=`date +"%m"`
 
echo "archive starting..."
echo "Starting archive at $LOG_TIME"

getfilelist

# Setting delimiter to an empty string since we want to read the entire line of the file
# and be able to handle files with spaces since the default is a space delimiter
SAVEIFS=$IFS
IFS=$''

((archived_moved=0))
while read file
do
  parsefilename $file
  echo "processing $filename with extension $extension"
  fDate=`stat -c %y "${file}"`
  fDate=$(echo "$fDate" | cut -d' ' -f1)
  #example  2018-01-12
    year=$(echo ${fDate} | cut -d'-' -f1 )
    month=$(echo ${fDate} | cut -d'-' -f2)
    day=$(echo ${fDate} | cut -d'-' -f3)
    filedate=${year}${month}
   if [ $(echo "$filedate" | grep -c '^[0-9]\{6\}$') -eq 1 ]
    then
        if [ ! -d ${archiveDir}${year}/${month} ]
        then
          echo "echo making directory $archiveDir$year/$month"
          mkdir -p ${archiveDir}${year}/${month}
        fi
        datepath="${year}/${month}"
        updatefilename
        echo "Archiving ${file} to ${archiveDir}${datepath}/$filename.$extension"
        mv "${file}" "${archiveDir}${datepath}/${filename}.${extension}"
        ((archived_moved=archived_moved+1))
        
    else
        echo "Couldn't get stat on ${reportBakDir}${file}"
    fi
done <"$ARCHIVEFILE"
IFS=$SAVEIFS
#END_TIME=`date |cut -c12-13,15-16,21-23| /usr/bin/sed s/" "//g`
END_TIME=`date`
echo "Completed archive at $END_TIME"
exit 0