I would like to be able to drop a folder on a script and have it go through the selected folder and each subfolder and sort the raw (.cr2) images and jpg images into separate folders named after the sourceFolder & “_Raw” or “_Jpg”
Currently I’m using Hazel to sort raw and jpg images into separate folders based on a few rules.
Hazel is becoming a bit of a pain to run and point to the correct folders, and I think it would be a lot easier to create a droplet I could put in my finder toolbar that could do the same thing.
Right now my hazel rules are:
If Kind is folder
Name does not end with Raw (so that it will skip folders that have already been sorted)
Name does not end with Jpg (so that it will skip folders that have already been sorted)
Name does not end with Stitched (folders that end with Stitched don’t need to be sorted)
Name does not end with Lidar (folders that end with Lidar don’t need to be sorted)
then run rules on the contents of the folder. (Including subfolders)
Then:
if extension is .jpg sort into subfolder named (sourcefolder)_Jpg
if extension if .cr2 sort into subfolder named (sourcefolder)_Raw
Thanks!
You could probably do it slowly via Finder scripting, or using System Events, but if you’re running macOS 10.10 or later AppleScriptObjC is a good bet:
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
on open {theFile}
set posixPath to POSIX path of theFile
set theNSURL to current application's |NSURL|'s fileURLWithPath:posixPath
my processFolderURL:theNSURL
set theNSURL to missing value
display dialog "Sorted." buttons {"OK"} default button 1
end open
on processFolderURL:folderURL
-- make file manager
set fileManager to current application's NSFileManager's new()
-- get contents of folder
set theURLs to fileManager's contentsOfDirectoryAtURL:folderURL includingPropertiesForKeys:{current application's NSURLIsDirectoryKey, current application's NSURLIsPackageKey} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value)
set theFiles to {} -- holds plain files
repeat with aURL in theURLs
-- is it a directory?
set {theResult, isDirectory} to (aURL's getResourceValue:(reference) forKey:(current application's NSURLIsDirectoryKey) |error|:(missing value))
if isDirectory as boolean then -- check it's not a package
set {theResult, isPackage} to (aURL's getResourceValue:(reference) forKey:(current application's NSURLIsPackageKey) |error|:(missing value))
-- is it not a package?
if not isPackage as boolean then
set theRange to (aURL's |path|()'s rangeOfString:"(Raw|Jpg|Stitched|Lidar)$" options:(current application's NSRegularExpressionSearch))
if |length| of theRange = 0 then -- no match
(my processFolderURL:aURL)
end if
end if
else -- plain file
set end of theFiles to aURL
end if
end repeat
if (count of theFiles) > 0 then my sortURLs:theFiles inFolder:folderURL
end processFolderURL:
on sortURLs:theFiles inFolder:folderURL
set theFiles to current application's NSArray's arrayWithArray:theFiles
-- make predicates and file manager
set predJpg to current application's NSPredicate's predicateWithFormat_("pathExtension ==[c]%@", "jpg")
set predRaw to current application's NSPredicate's predicateWithFormat_("pathExtension ==[c]%@", "cr2")
set fileManager to current application's NSFileManager's new()
-- process results
set theJpegs to (theFiles's filteredArrayUsingPredicate:predJpg) -- extract .jpg files
if theJpegs's |count|() > 0 then
-- create _Jpg folder if necessary
set folderName to folderURL's lastPathComponent()
set newFolderURL to (folderURL's URLByAppendingPathComponent:(folderName's stringByAppendingString:"_Jpg"))
(fileManager's createDirectoryAtURL:newFolderURL withIntermediateDirectories:true attributes:(missing value) |error|:(missing value))
-- move files
repeat with aJpg in theJpegs
(fileManager's moveItemAtURL:aJpg toURL:(newFolderURL's URLByAppendingPathComponent:(aJpg's lastPathComponent())) |error|:(missing value))
end repeat
end if
set theRaws to (theFiles's filteredArrayUsingPredicate:predRaw) -- extract raw files
if theRaws's |count|() > 0 then
-- create _Raw folder if necessary
set folderName to folderURL's lastPathComponent()
set newFolderURL to (folderURL's URLByAppendingPathComponent:(folderName's stringByAppendingString:"_Raw"))
(fileManager's createDirectoryAtURL:newFolderURL withIntermediateDirectories:true attributes:(missing value) |error|:(missing value))
repeat with aRaw in theRaws
(fileManager's moveItemAtURL:aRaw toURL:(newFolderURL's URLByAppendingPathComponent:(aRaw's lastPathComponent())) |error|:(missing value))
end repeat
end if
end sortURLs:inFolder:
Shane, this works beautifully! Thank you so much 