Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

macstatic

macrumors 68020
Original poster
Oct 21, 2005
2,025
165
Norway
I have the following terminal command for Exiftool (which adds an EXIF date/time header to files which don't have them already (typically scanned images) and copies the OSX file creation date to it):

Code:
exiftool -r '-alldates<MDItemContentCreationDate' -keywords+=DateModified  -if '!$datetimeoriginal' . -overwrite_original

In the OSX Terminal I first "cd" to the folder with the files I want processed, then issue the above command which works as prescribed.

Preferring the Mac way of doing things instead of the command line, is there a way I can add an icon for this to OSX dock, then be able to "drag & drop" a bunch of files to it (or a folder with files inside)? Alternatively, or in addition to this; could I also select a bunch of files (or a folder) then right-click to access an OSX "Service" to do this as well?
 
Basically, you put the command-line into an Automator workflow, and the workflow accepts drag-n-drops, runs the command, etc.


The first decision to make in Automator is what kind of workflow to make. It should be an Application, because this is what accepts items dropped onto it.

The second decision is what action to add. Its a Run Shell Script action.

The third decision is how to pass input and you should choose "as arguments". This choice will also give you a different shell command prototype to work from ("to stdin" has a "cat" prototype).

Frankly, at this point you should save it and try running it. All it will do is echo things dropped on it, but it should give you a sense of the steps that are happening. You should also spend a little time looking at the output, and understand how to read the results.

You may then need to add another step before Run Shell Script to feed it example files. Use a "Get Specified Finder Items" action, and put it BEFORE Run Shell Script. Add some example files to it. Run it and look at the results with just the prototype shell script. You can disable this step later (right-click on it, choose "Disable" from contextual menu).

Next, it's time to edit the Run Shell Script's prototype. Change the echo "$f" line in the shell script to be your exiftool command line. Test again. Check that the exiftool command worked by doing whatever is needed to check the date.

Make sure you have verified backups of every image file you use in testing. If you completely bork the image files, you can restore them. If you're working without a safety net, not so much.


You'd build a Service in Automator in pretty much the same way. The main difference is it's a Service workflow instead of an Application one.

Again, I advise starting with the prototype shell script, testing it, confirming it works.


If you run into a problem, post again. If there's an error message, copy and paste the complete message and post it exactly as it appears.

Programming is often a process of adding incremental changes to something that already works, and confirming it still works, but with whatever incremental change you made. This is so if you make a mistake (and you will, many times), you can more easily go back to the last thing that worked and try again.
 
Last edited:
Basically, you put the command-line into an Automator workflow, and the workflow accepts drag-n-drops, runs the command, etc.


The first decision to make in Automator is what kind of workflow to make. It should be an Application, because this is what accepts items dropped onto it.

The second decision is what action to add. Its a Run Shell Script action.

The third decision is how to pass input and you should choose "as arguments". This choice will also give you a different shell command prototype to work from ("to stdin" has a "cat" prototype).

Frankly, at this point you should save it and try running it. All it will do is echo things dropped on it, but it should give you a sense of the steps that are happening. You should also spend a little time looking at the output, and understand how to read the results.

Thanks for your exceptionally clear and educational instructions! I've learnt a lot.
Looks good so far. I had to put a "Get specified Finder items" at the beginning, and add my test image folder to it for testing purposes within Automator.
I didn't change the default shell script before testing, and when pressing "Run" the results at the bottom of the window showed the folder path along with a green tick which I interpret as all being OK.



You may then need to add another step before Run Shell Script to feed it example files. Use a "Get Specified Finder Items" action, and put it BEFORE Run Shell Script. Add some example files to it. Run it and look at the results with just the prototype shell script. You can disable this step later (right-click on it, choose "Disable" from contextual menu).
Right, just for testing purposes it seems.

Next, it's time to edit the Run Shell Script's prototype. Change the echo "$f" line in the shell script to be your exiftool command line. Test again. Check that the exiftool command worked by doing whatever is needed to check the date.

This is the complicated part and I first thought you meant replace that entire line (shown in bold above) with ther Exiftool terminal command, but receiving an error message I tried to replace just $f with the terminal command (again within quotes) and pressing "Run" gave me an all OK in the results section, so I must have done something right.
In other words, my shell script looks like this:
Screen Shot 2016-02-13 at 09.56.20.png



Make sure you have verified backups of every image file you use in testing. If you completely bork the image files, you can restore them. If you're working without a safety net, not so much.

Yes, I've created an "originals" folder and of course a "test" folder. After testing I can replace the files with a fresh batch from the "originals" folder. All copies of course!!
So at this stage, if everything is set up correctly, the files should actually be processed by Exiftool, or just simulated to do so? None of the files have had their Exif data change so either it doesn't work (despite the green tick alongside "results") as you can see here along with the results:

Screen Shot 2016-02-13 at 10.05.34.png
 
...
So at this stage, if everything is set up correctly, the files should actually be processed by Exiftool, or just simulated to do so? ...
Given what you posted, it's just simulating the command. More specifically, it's echoing the text of a command, but it's not actually executing it.

So you now have the basic structure in place. Next, you have to put the command in there correctly. To do that, we have to understand exactly what the original was doing, and what this script is expected to do.


First, the original consists of two commands, not one. The "cd" to the folder with the files I want processed is a crucial command, because it sets the context for the 'exiftool' command line. Without the correct directory, the 'exiftool' command won't do what you want.

Second, the way the command-line is written, it processes an entire directory of files, recursively (I looked this up in the online 'exiftool' man page). So the script will have to do the same thing. This implies that the Automator workflow should only process folders dropped onto it. The shell script can do that, but it will be easier to understand if you use another Automator action.

The Automator action is "Filter Finder Items". Place it before the "Run Shell Script" action. Then use the popups to select these:
(All) of the following are true
(Kind) (is) (folder)​
I've shown the popups as parenthesized words.

To test, you should revert to the echo "$f" command, and make sure that only folders appear in Results. That is, if you drop files on it directly, or in the "Get specified Finder items" action, those files should be ignored, and not appear in the Results output.


Next, it's important to understand what the "$f" represents. It's each item produced by the prior action, which should only be folder names.

There are two ways to handle this folder. You could 'cd' to it, then run the 'exiftool' command line, just like you did manually. Or you can skip the 'cd' command and tell 'exiftool' to work directly on the folder. I'll show the command-line for the 2nd.

Replace the entire script in the Run Shell Script step with this:
Code:
for f in "$@"
do
    exiftool -r '-alldates<MDItemContentCreationDate' -keywords+=DateModified  -if '!$datetimeoriginal' "$f" -overwrite_original
done
You should be able to copy and paste that exactly as shown.

Notice that I've replaced the dot in the original with "$f" (the quotes are required). That original dot means "the current directory", which in the original context means "the directory you just cd'ed to".

Here, the "$f" means "the input item", and the quotes ensure that any spaces or other special characters are kept as part of the folder name.

If you run the workflow at this point, you should be getting folders of images with the creation date changed. Test it.

If everything works, you can disable the "Get specified Finder items" action (right-click it, choose "Disable"). You could also delete it, but if you ever have to revise the workflow, you'd probably add it back. Disabling preserves the step without running it. Again, test this.


As an exercise, you could try the two-command version yourself. That is, write the shell commands that 'cd' to the folder, then run 'exiftool' on it.
 
Last edited:
Second, the way the command-line is written, it processes an entire directory of files, recursively (I looked this up in the online 'exiftool' man page). So the script will have to do the same thing. This implies that the Automator workflow should only process folders dropped onto it.

I would like the script to be as flexible and "idiot proof" as possible -would it be possible to allow both a file/several files as well as folders to be used with it?

OK, so I've tried set up the script with these items:

- Get specified Finder items (with the path of the test folder)
- Filter Finder items (using the filter options you suggested)
- Run shell script (with the default setup (echo "$f" etc. and witg "Pass input: [as arguments])

...and the log at the bottom of the window enabled
In the "Get specified Finder items" I've added the image test folder (with a variety of image files). When I press the "run" button all appears to work fine (the log gives me a green ticked "Workflow completed).
If I replace the test folder (in "Get specified Finder items) with the path to just a test image, then run it I get the same result, so all looks fine so far.

However, if I replace the default shell script content with the one for exiftool as you suggested, point to the image test folder in the "Get specified Finder items" section then press the Run-button I get a red icon in the log along with an error message saying:

Run shell script error - 1 error
Can't locate image/ExifTool.pm in @Inc (@Inc contains: /usr/bin/lib /Library/Perl/5.16/darwin-thread-multi-2level......


(I haven't bothered to include everything here as the log lines don't wrap and can't be copied and pasted into here either, but I hope the info is still sufficient).
But if I replace the test folder path with just a test image file, then run it I get a green ticked "Workflow completed".
Still, the script doesn't seem to actually affect the file as no date has been added to its EXIF info (I use Preview with its "Tools-Show Inspector" enabled).

I'll triple check everything and re-read what you've just written in case I missed something, but so far it appears I've done things right so I'm a little stuck.
 
...
However, if I replace the default shell script content with the one for exiftool as you suggested, point to the image test folder in the "Get specified Finder items" section then press the Run-button I get a red icon in the log along with an error message saying:

Run shell script error - 1 error
Can't locate image/ExifTool.pm in @Inc (@Inc contains: /usr/bin/lib /Library/Perl/5.16/darwin-thread-multi-2level......
I googled the error message you posted "Can't locate image/ExitTool.pm" and found some posts on other forums. You might find an answer by doing the same thing.

The malfunction is probably in the realm of the tool itself. That is, something about the tool or its environment is causing the malfunction. I don't know what that might be, because I don't have 'exiftool' here.


There are commands you can run in Terminal and also in your Run Shell Script that will print the environment, and you can then compare them and see the differences. That might provide a clue to the cause. Differences could be innocuous or important; it depends.

In Terminal:
Code:
export >~/Desktop/env-term.txt
This produces a file of 'export' commands, with variable-names and values. It'll appear on your Desktop.

For the Run Shell Script, put this on a line before the for f in "$@":
Code:
export >~/Desktop/env-script.txt
It also produce a file on your Desktop. Open them both and find the differences. If you're unsure, post both files within CODE tags.


You can also redirect the error message to a text file, which can then open in TextEdit and post here. This may help you discover the cause, or help you in your googling for other people with similar results.

Use this line in your shell script, within the do ... done:
Code:
  exiftool -r &>~/Desktop/err.txt  '-alldates<MDItemContentCreationDate' -keywords+=DateModified  -if '!$datetimeoriginal' "$f" -overwrite_original
Also try adding a -v option to the exiftool command line to increase the verbosity. It might be useful.
 
Thanks. I've generated the two export files and they look pretty similar except the the one from the OSX Terminal has a few more path variables. Here's a comparison:

env-script.txt:
declare -x PATH="/usr/bin:/bin:/usr/sbin:/sbin"

env-term.txt:
declare -x PATH="/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/opt/ImageMagick/bin"

The rest of the variables appear to be identical.

Next, the "err.txt" file from the code in the script (an additional -v (or adding it to the existing option (exiftool -rv) didn't make any difference in the resulting file):
Can't locate Image/ExifTool.pm in @Inc (@Inc contains: /usr/bin/lib /Library/Perl/5.16/darwin-thread-multi-2level /Library/Perl/5.16 /Network/Library/Perl/5.16/darwin-thread-multi-2level /Network/Library/Perl/5.16 /Library/Perl/Updates/5.16.2 /System/Library/Perl/5.16/darwin-thread-multi-2level /System/Library/Perl/5.16 /System/Library/Perl/Extras/5.16/darwin-thread-multi-2level /System/Library/Perl/Extras/5.16 .) at /usr/bin/exiftool line 30.
BEGIN failed--compilation aborted at /usr/bin/exiftool line 30.


If I didn't know any better I'd say it seems that a bug has been detected in Exiftool by how we've been using it....
 
Thanks. I've generated the two export files and they look pretty similar except the the one from the OSX Terminal has a few more path variables. Here's a comparison:

env-script.txt:
declare -x PATH="/usr/bin:/bin:/usr/sbin:/sbin"

env-term.txt:
declare -x PATH="/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/opt/ImageMagick/bin"

The rest of the variables appear to be identical.

Next, the "err.txt" file from the code in the script (an additional -v (or adding it to the existing option (exiftool -rv) didn't make any difference in the resulting file):
Can't locate Image/ExifTool.pm in @Inc (@Inc contains: /usr/bin/lib /Library/Perl/5.16/darwin-thread-multi-2level /Library/Perl/5.16 /Network/Library/Perl/5.16/darwin-thread-multi-2level /Network/Library/Perl/5.16 /Library/Perl/Updates/5.16.2 /System/Library/Perl/5.16/darwin-thread-multi-2level /System/Library/Perl/5.16 /System/Library/Perl/Extras/5.16/darwin-thread-multi-2level /System/Library/Perl/Extras/5.16 .) at /usr/bin/exiftool line 30.
BEGIN failed--compilation aborted at /usr/bin/exiftool line 30.


If I didn't know any better I'd say it seems that a bug has been detected in Exiftool by how we've been using it....
My guess is that 'exiftool' depends on something in /opt/ImageMagick/bin. That's just a guess, though, since the only investigation I did was googling the keywords exiftool imagemagick , which didn't show anything obvious.

One wonders how your Terminal PATH acquired the extra items. Maybe when you installed exiftool, the installer did that.

To make the PATH values the same, add this line at the top of your Run Shell Script script:
Code:
export PATH="$PATH:/usr/local/bin:/opt/X11/bin:/opt/ImageMagick/bin"

If that makes it work, you can narrow down the required directory by eliminating pathnames between colons, starting at the end. That is, try this:
Code:
export PATH="$PATH:/usr/local/bin:/opt/X11/bin"
Next, try this:
Code:
export PATH="$PATH:/usr/local/bin:/opt/ImageMagick/bin"
then this:
Code:
export PATH="$PATH:/opt/X11/bin:/opt/ImageMagick/bin"

If the first change I've shown doesn't work, then ask again, as I have some other things to try.
 
I don't think ImageMagick has anything to do with Exiftool. It's just something I installed at some time to try out.
Regarding the path I should have mentioned that I did have some issues with my Mac accessing Exiftool as it didn't find it. Strangely, on my other Mac (also with OSX 10.9.5) it runs without any issues.
The solution was to define the path, so in my ".bash_profile" I have the following line which made it work immediately:

Code:
alias exiftool='/usr/local/bin/exiftool'

Just thought I'd mention this right in case it could be the reason for those problems.

I'll try your suggestions and see what happens.

UPDATE: I've just tried all the path commands you suggested but none of them made the (same error message as before) go away.
 
I don't think ImageMagick has anything to do with Exiftool. It's just something I installed at some time to try out.
Regarding the path I should have mentioned that I did have some issues with my Mac accessing Exiftool as it didn't find it. Strangely, on my other Mac (also with OSX 10.9.5) it runs without any issues.
The solution was to define the path, so in my ".bash_profile" I have the following line which made it work immediately:

Code:
alias exiftool='/usr/local/bin/exiftool'

Just thought I'd mention this right in case it could be the reason for those problems.

I'll try your suggestions and see what happens.

UPDATE: I've just tried all the path commands you suggested but none of them made the (same error message as before) go away.
Well, I'm stumped.

I can't think of a reason why you'd need to alias 'exiftool' like you've shown, because /usr/local/bin is already in your PATH. That is, the shell should find it without you needing to make an alias.

Incidentally, if your Terminal windows are relying on your .bash_profile, you can tell the "Run Shell Script" to load the commands in that file. Maybe that will make things work.

Add this line at the top of the shell script:
Code:
source ~/.bash_profile

At this point, you should probably post the entire contents of your Run Shell Script script, within CODE tags. There's been a lot of add this, remove that, so maybe seeing exactly what you have now will be a clue.
 
I think I'm going to start from scratch, following your instructions on my other Mac (where I didn't have to define the path of Exiftool) and see if it all works there.
If there's a problem with my main Mac it's quicker and easier to troubleshoot that way.

PS: I just tried adding the above code to the shell script but it didn't make any difference.
 
Hey, it worked on my laptop!!! :) That is, the script worked (I've only tested it within the Automator application so far) without any error message and my test files got their EXIF date tags as intended.
So obviously there's something wrong with my MacPro setup which needs reinstalling. Until then I'll keep testing with my Macbook Pro instead.

At first I was told exiftool couldn't be found, so I added the full path to the script which fixed that (I don't have any .bash_profile on the laptop, but it could find it in the terminal anyway).
So, just to avoid any confusion, here's the Automator script I've just tested and succeeded with on the laptop:

- Get specified items (the image test folder is dragged into here)
- Filter Finder items:
[All] of the following are true:
[kind] [is] [folder]

- Run shell script
Shell: [/bin/bash] pass input: [as arguments]
Code:
for f in "$@"
do
    /usr/local/bin/exiftool -r '-alldates<MDItemContentCreationDate' -keywords+=DateModified  -if '!$datetimeoriginal' "$f" -overwrite_original
done

Looking very good so far, so next I'm going to re-read your replies and do some more testing to see if I can get it fully working as intended now that I've uncovered the main problem.
 
At first I was told exiftool couldn't be found, so I added the full path to the script which fixed that (I don't have any .bash_profile on the laptop, but it could find it in the terminal anyway)..
Congrats on getting it going.

Giving the full pathname to exiftool is a perfectly good way of solving the "Can't be found" problem. This is probably due to differences in PATH.

There are several possible profile files that bash can read from. One of those might exist and cause Terminal to set the PATH with /usr/local/bin in it. Do this command in Terminal, post the output in code tags:
Code:
ls -la ~
 
I've been working on the actual Exiftool command the past few weeks so I hope someone's still reading this thread ;)

Here's the improved Exiftool command which works great in the OSX Terminal, but for some reason I can't get it to work properly in Automator even though I think I've adapted it for Automator as you posted about earlier. Oddly enough I can't get the original script to work without errors either, on the same laptop.
Amongst all the testfiles I might have ended up with a new script written from scratch based on what I've posted here, but I'm puzzled.
Anyway, here's the improved Terminal command which I want to use instead of the old one for a "drag & drop" application:

Code:
exiftool -r "-XMP-Exif:DateTimeOriginal<MDItemContentCreationDate" "-XMP-xmp:ModifyDate<MDItemContentCreationDate" -P -overwrite_original_in_place -if 'not $exif:datetimeoriginal' .

I did check the environment variable where it turns out that Automator doesn't see the /usr/local/bin/ path (Exiftool is located at /usr/local/bin/exiftool) so I added it to the top of the shell script. Still, entering the full path for exiftool instead should work just as well, shouldn't it?
OK, just to eliminate any obvious issues, here's what I've done in Automator:

1) created an Automator "Application"
2) "Get specified items" action (with the test image folder added)
3) "Filter Finder items" action with this setup:
[all] of the following are true: [kind] [is] [folder]
4) "Run shell script" action with "/bin/bash" shell and "Pass input as arguments" with the following:
Code:
export PATH="$PATH:/usr/local/bin"
for f in "$@"
do
    exiftool -r '-alldates<MDItemContentCreationDate' -keywords+=DateModified  -if  '!$datetimeoriginal' "$f" -overwrite_original
done


UPDATE: I just noticed a small, but apparently significant detail: if I remove the space between -if and '!$datetimeoriginal' I also eliminate any minor exiftool errors as the ones I'm trying to eliminate in PNG files (adding EXIF headers to them is apparently tricky though I'm getting there). Some of the Automator errors might actually have been due to the various PNG files I've been testing with (different files contain or miss different EXIF, XMP etc. tags).
I'll see if I can get a similar result in Automator with the new exiftool command above...

PS: how do I add comments to the Automator shell script? I'm assuming a hash character (I can't seem to actually write it here as it confuses the forum posting and won't let me do it) at the start of a line, but is this regardless of word-wraps, just depending on a line break character (pressing RETURN)?

UPDATE 2: OK, I think I might have figured it out. I slightly moved things around with the exiftool command like this:
Code:
export PATH="$PATH:/usr/local/bin"
for f in "$@"
do
exiftool -r "-XMP-Exif:DateTimeOriginal<MDItemContentCreationDate" "-XMP-xmp:ModifyDate<MDItemContentCreationDate" -if 'not $exif:datetimeoriginal' "$f" -P -overwrite_original_in_place
done

Does its syntax look correct? As with the previous script, removing the space after the -if also removed any minor error messages. Why does this make a difference, and will it cause other issues if I do this?
 
Last edited:
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.