Contents

Sopi

Sopi (Sort Pictures) is a simple Julia program written by Fabrice that takes a list of files from our camera (with extension "JPG") and move them in a directory tree named after the date, also appending the hour of the shot to the filename itself.

This replaces the script SortTime which we were using until then but that was taking too much time to be convenient (over a second per file). Testing on 563 files from our last batch of pictures, it reduced the 17min37s of SortTime to 1min9s, which is more reasonable!

Usage

Install sopi in a binary directory (e.g., /usr/bin) as an executable; It relies on exiftool which can be installed with sudo apt install libimage-exiftool-perl.

Run on the destination directory:

sopi /home/laussy/pics/

Sopi won't run if not given a directory. To work in the current directory:

sopi .

To work on various directories, put them in a file dirs.txt and call

cat dirs.txt | xargs -I '{}' sopi {}

History

Todo

There should be an option to add the timestamp to the image itself which can be done by hand by uncommenting the following:

#    mv(lfn[i],dest[1]*lmonths[:,2][parse(Int64,dest[2])]*dest[3]*"/"*replace(replace(lfn[i],".JPG"=>"-"),".jpg"=>"-")*alltimes[i,2]*".jpg")

This is not needed for photos that come from the phone, which are already tagged, but is necessary for those of the camera.

Source

#!/bin/sh
#  ____              _ 
# / ___|  ___  _ __ (_)
# \___ \ / _ \| '_ \| |
#  ___) | (_) | |_) | |
# |____/ \___/| .__/|_|
# v°0.2       |_|      
# Fri  1 Jan 18:50:20 CET 2021
# F.P. Laussy - fabrice.laussy@gmail.com
# 
# Sopi sorts jpg files in a directory tree named after the dates
# at which the pictures have been taken (after their exif data)
# (`sopi' stands for Sort Pictures)
#
#=
exec julia -O3 "$0" -- $@
=#

using Dates;

# Goes to given directory if one is given as argument
# If not argument given, exit (for safety)
if length(ARGS)!=0
   cd(ARGS[1])
   else
       println("The working directory must be given as argument")
       println("To process files in the current directory, use:")
       println(" sopi .")
       exit()
end
       
# This list the filenames of JPG files to process (in current path)
lfn=filter(x->occursin("JPG",x), readdir());

# Starting
println("Hi there! Sopi working with "*string(length(lfn))*" files in "*pwd())

print("Started ");
print(now());
print("\n")

# This returns a vector with date and time from the exif data
function datemy(fn)
 mdata = read(`exiftool $fn`,String)
 sdata=split(mdata,"\n")
 spdata=split(sdata[findall( x -> occursin("Date/Time Original", x) , split(mdata,"\n"))[1]]," ")
 [spdata[end-1],spdata[end]]
end

# This collects all the dates and times to process and transform into a matrix
alltimes=permutedims(reduce(hcat,[datemy(i) for i in lfn]))

# Keep unique days
uniquetimes=(x->replace(x, ":"=>"/")).(unique(alltimes[:,1]))

# This creates the directory tree
lmonths=["/01/" "/01-January/"; "/02/" "/02-February/"; "/03/" "/03-March/"; "/04/" "/04-April/"; "/05/" "/05-May/"; "/06/" "/06-June/"; "/07/" "/07-July/"; "/08/" "/08-August/"; "/09/" "/09-September/"; "/10/" "/10-October/"; "/11/" "/11-November/"; "/12/" "/12-December/"]

for i=1:12
 global uniquetimes=(x->replace(x,lmonths[i,1]=>lmonths[i,2])).(uniquetimes[:,1])
end

print("Working with "*string(length(uniquetimes))*" directories...\n")
mkpath.(uniquetimes)

print("Moving files!\n")
# This puts the files in pla
for i=1:length(lfn)
 dest=split(alltimes[i,1],":")
 mv(lfn[i],dest[1]*lmonths[:,2][parse(Int64,dest[2])]*dest[3]*"/"*replace(lfn[i],".JPG"=>"-")*alltimes[i,2]*".JPG")
end

print("Finished ")
print(now())
print("\n")