Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

Automator - jpeg and raw file movement

OS X 10.10.3

4k iMac and early 2009 Mac Pro


I have 2 file locations. Location "A" has jpegs and Location "B" has RAWs. Location "A" has ~700 images that are to be edited, but location "B" has ~10,000 images (most will not be edited).


The files in Location "A" have a matching RAW file in Location "B". The file name is the same, but the extension is .CR2 instead of .jpg. I want to move all the corresponding RAW files from Location "B" that match the file name of the jpegs in Location "A" to Location "C" (any user input destination).


Is this possible with a service? Any help in writing this service would be appreciated. I'm not sure on the best place to start.


Thanks

Mac Pro, OS X Yosemite (10.10.3)

Posted on May 15, 2015 1:45 PM

Reply
16 replies

May 15, 2015 4:19 PM in response to iWorkToGolf

The following script should do what you are asking for. It's not a service, but might serve as a good starting point. The script assumes that your first two folders are located at the first level of the Pictures folder. The destination folder, chosen by the user, may be located anywhere.


set theDestinationFolder to choose folder


set theBasePath to path topictures folderastext

set name1 to "Folder A"

set name2 to "Folder B"

set folder1 to (theBasePath & name1) as alias-- for JPEGs

set folder2 to (theBasePath & name2) as alias-- for RAWs


set theFilesToMove to {}


tell application "Finder"

set extension hidden of files of folder1 to true

set theDisplayedNames to displayed name of files of folder1

repeat with thisName in theDisplayedNames

try

set thisFile to (theBasePath & name2 & ":" & thisName & ".CR2") as alias

copy thisFile to the end of theFilesToMove

end try

end repeat

movetheFilesToMovetotheDestinationFolder with replacing

end tell

May 15, 2015 5:26 PM in response to Pierre L.

I don't know much about Automator. However, in order to get the service you are asking for (at least in Finder),

just replace

set theDestinationFolder to choose folder

with

tell application "Finder" to set theDestinationFolder to choose folder

in my previous script,

and then copy the script into the following Automator window. I have tested it: it works flawlessly.User uploaded file

Moreover, you can easily move the RAW files back into their original folder just by typing ⌘Z (Undo Move of…).

May 16, 2015 4:22 PM in response to iWorkToGolf

Here is how this is done in PyObjC, which has been tested as an Automator {Service, Application} on OS X 10.9.5, and 10.10.3. It makes assumptions about the location of the jpg folder A, and the raw folder B, but none about the destination folder, as this is chosen via an AppleScript choose folder dialog from the script. It does not assume all jpg are lowercase extensions. It does assume that all raw extensions are upper-case CR2. When processing is complete, it drops down a user notification panel with a count of the files moved to the destination folder.


As the Script is self-contained, it only requires a Run Shell Script Automator action, from the Utilities Library, added to the Workflow. For the shell, one choses Python instead of the default Bash. If it is to be a Service, then it receives no input from any application. If an Application, pass input can be ignored, as the application is not looking for Automator input. Select all of the Python boilerplate, and remove it. Copy/paste the following Python script into this Run Shell Script window, and then Automator > Save… to your Desktop (if application) and give it a meaningful name. Double-click to launch folder chooser.


Code


#!/usr/bin/python

# -*- coding: utf-8 -*-

'''

A Python/Objective-C application that prompts for a user-specified

destination folder, matches a folder of jpg files to their name

equivalence in another folder containing raw cr2 image files, and

finally moves the matched raw files into the destination folder.

'''

from Foundation import (

NSAppleScript,

NSUserNotification,

NSUserNotificationCenter

)

import shutil

import locale

import os

import sys


folder_a = os.path.expanduser('~/Pictures/folderA')

folder_b = os.path.expanduser('~/Pictures/folderB')

valid_extension = ['.jpg', '.JPG', '.cr2', '.CR2']

match_index = []

raw_ext = '.CR2'

title = 'Raw File Processing Facility'


as_str = '''

property defloc : path to pictures folder

try

tell application "Finder"

activate

set destFolder to POSIX path of (choose folder default location defloc invisibles no)

end tell

on error msg number enbr

return "None"

end try'''


def is_image_file(filename, extensions=valid_extension):

''' return filename only on valid extension '''

return any(filename.endswith(e) for e in extensions)


def notify(title, subtitle, text):

''' User Notification panel '''

notification = NSUserNotification.alloc().init()

notification.setTitle_(str(title))

notification.setSubtitle_(str(subtitle))

notification.setInformativeText_(str(text))

# notification.setSoundName_("NSUserNotificationDefaultSoundName")

(NSUserNotificationCenter.defaultUserNotificationCenter().

scheduleNotification_(notification))


def main():

# Prompt for user-specified destination folder

t = NSAppleScript.alloc().initWithSource_(as_str)

result = t.executeAndReturnError_(None)

dest_folder = result[0].stringValue().encode('utf-8')


# user clicked Cancel, did not choose a folder, or AppleScript error

if ('None' in dest_folder

or dest_folder == os.path.expanduser('~/Pictures/')):

s = 'Bad user input'

m = 'No files processed.'

notify(title, s, m)

sys.exit(1)

# Strip extension from all valid jpg and replace with CR2 for indexing.

for name in filter(is_image_file, os.listdir(folder_a)):

match_index.append(os.path.splitext(name)[0] + raw_ext)

# Get a list of all raw (CR2) files.

raw_files = os.listdir(folder_b)

# Match jpg to cr2 and build move list

move_files = list(set(match_index).intersection(raw_files))

# Move the files to destination. Behaves like UNIX mv command.

for name in move_files[:]:

(shutil.move(os.path.join(folder_b, name),

os.path.join(dest_folder, name)))

locale.setlocale(locale.LC_ALL, '')

# handle number punctuation automatically by default locale

s = 'Processing Complete'

m = "{:n}".format(len(move_files)) + ' files moved.'

notify(title, s, m)

if __name__ == '__main__':

sys.exit(main())

May 18, 2015 2:41 PM in response to iWorkToGolf

Before I posted that Python code, I visited every one of those 85 lines and verified proper Python code alignment on tab boundaries in this site editor. After I hit reply, the JIVE hosting environment inserted spaces where there were none, and changed code alignment on non-tab boundaries. Effectively, the Python script is useless when copied from my post, as every line of code will need to be inspected, spaces removed, and code re-aligned on proper tab boundaries again — before it will work in the Terminal, or Automator. That would need to be done in a proper programmer's editor — not Script Editor.


At this point, I would suggest you and Pierre focus on his AppleScript contribution. Sorry for the lost time.

May 18, 2015 2:52 PM in response to VikingOSX

I just tested the Advanced Editor and pasting correct Python code into the Python Syntax template. When that code is posted, and copied back into a Programmer's Editor (Sublime Text 3), every line of Python code has two spaces appended to it, even though it appears to honor proper tab alignment. Same result. Code won't work without fixing the trailing spaces.

May 19, 2015 6:30 AM in response to VikingOSX

Viking,


I fixed the spacing (in sublime text) and your code is phenomenal. Thank you so much for your help with this, and everyone else who posted solutions.


Pierre,


I did try your script in Script Editor, but I couldn't get it to work. I wouldn't mind working with that some more. Thanks you so much for your help too! Here's a screen shot... There's a high likelihood that I'm doing something very wrong (like using the wrong folder names). I pointed the output to Folder C.


User uploaded file

May 19, 2015 7:42 AM in response to iWorkToGolf

Nice that you had Sublime Text. 😉 How is the script performance on your image folders?


Out of frustration, and for those without this advanced editor, I wrote a sed script that eliminates all Jive hosting format issues except for these exceptions:

  • 2 lines

    Needed to outdent inline function comment to nearest tab boundary.

  • 1 line

    Extra, unnecessary newline (62) that causes a too many blank lines warning on line (63).

  • 1 line

    The or condition on line (64) needed an extra tab to indent under the 'e' in None above it.

  • 1 line

    Continuation line (80) under indented, needed one additional space to suppress the under-indent warning.


Still working on these five. This will allow (within reason) copied/pasted Python code from the community site into a plain-text TextEdit document, and the sed script (when fixed) will output functional formatted Python source. I use Anaconda, the Python IDE in Sublime Text 3 for development.

May 19, 2015 8:19 AM in response to VikingOSX

It's working perfectly. If there's a way to contact me or vice versa, do so and your next beer or coffee is on me.

I'm sure this is possible but not sure on how hard: Is there a way to generate a log file of any jpgs that did not have a matching .CR2? I also was curious about the folder paths at the top of the script. If I want to change those to another HDD, would it look like this:

folder_a = os.path.expanduser('/volumeName/path/to/folder')

or is it more complicated to change the working directory?

Thanks again

May 19, 2015 9:32 AM in response to iWorkToGolf

iWorkToGolf wrote:


I'm sure this is possible but not sure on how hard: Is there a way to generate a log file of any jpgs that did not have a matching .CR2?


That can be also be done with the Run Shell Script Action:


for f in $1/*.jpg
do
  basename=${f##*/}
  StripExt=${basename%.*}
  Raw="$HOME/Desktop/B/$StripExt".CR2
  if [ -f "$Raw" ] ; then
       mv "$Raw" $HOME/Desktop/C
  else
       echo "No Matching CR2 for "$f"" >> $HOME/Desktop/NoMatchCR2.txt
  fi
done

May 19, 2015 11:18 AM in response to VikingOSX

is there a cleaner way to do this:


os.chdir('../../../volumes/TempStorage')


folder_a = os.path.expanduser('_jpegs')

folder_b = os.path.expanduser('_raws')


assuming that TempStorage is the name of another volume, and _jpegs and _raws are both folders within that directory.


I'm not sure if there would be any repercussions to changing the directory in that way if the script is run multiple times.

May 19, 2015 12:14 PM in response to iWorkToGolf

I got into the habit of using os.path.expanduser() because I can provide full paths, or have tilde paths expanded to full paths. You can specify os.path.expanduser('/Volumes/TempStorage/_jpegs').


There is a way to arrive at a set of images in folder_a that do not match in your raw folder? Yes. Is there a way to log these? Yes.


Here is a screencapture of the code for jpg images that were not in the raw folder. Put this code after the shutil code where the files are moved, as this is the last thing you want to do. Create another constant for jpg_ext.

User uploaded file


The ability to log these files to a LOGFILE is in the following code. Put the LOGFILE constant at the end of the variable list before the function definitions. Put these two functions after the is_image_file function. Don't forget to import time among the other import statements.

User uploaded file

Automator - jpeg and raw file movement

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.