How do I use a List to Select Specifc a Photoshop Action


#1

Hi,

wondered if anybody could give a few pointers on a script i’m writing

Aim
I want to use a list to extract different cobinations of files* from a defined folder, I would then like that same list selection to choose between mutliple photoshop actions and run the extracted file combination through that action.
*extracted files have a standardised naming convention

Current Issues

-getting the returned list selection to run the photoshop action

-how to repeat the action on multiple images.

Project Breakdown

Stage 1
-on opening run a list

-List to conatain a set of names relating to photoshop actions

-select action name from list

Stage 2
-choose folder with source images (always 14 images always with the same last 9 characters _0000.tif to _0013.tif)

-Choose a save folder

Stage 3
-dependant on original list selection, gather files from source image folder and run them through a coresponsing photoshop action

e.g If “Action 1” selceted from List select image “_0001.tiff & _0010.tif” from source folder and do photoshop action “Action1”

Stage4
-save in chosen “save folder”

Current Script

--Stage 1--

set PhotoshopActionList to {"Action1", "Action2", "Action3", "Action4", "Action5"}

set ActionrequiredAnswer to choose from list PhotoshopActionList with title "Actions Picker"       with prompt "Choose Action?"


if ActionrequiredAnswer is false then
error number -128 (* user cancelled *)
else
set ActionrequiredAnswer to ActionrequiredAnswer's item 1 (* extract choice from list*)
end if

end run

--Stage 2--

property SourceFolder : missing value
property destinationFolder : missing value

if SourceFolder = missing value then
set SourceFolder to (choose folder with prompt "Choose Base Images:")
set destinationFolder to (choose folder with prompt "Choose Save Location:")
else

tell application "Finder"
set theFolders to every item of entire contents of SourceFolder as list
repeat with thisFolder in theFolders
make new alias file at destinationFolder to thisFolder
end repeat
end tell
end if

--Stage 3--

tell application "Finder"
set filesList to {files of entire contents of SourceFolder contains "_001", "_002", "003"} as    alias list
end tell

tell application "Adobe Photoshop"
repeat with aFile in filesList
open aFile

do action "Action1" from "Actionsfolder"
end tell

--Stage 4--

save currentDocument in folder destinationFolder as JPEG

Thanks


(CK) #2

I can offer a few notes on the AppleScript, bearing in mind I don’t have Photoshop so have no idea whether or not it is scriptable (I’m assuming it is), and whether your AppleScript terminology for Photoshop is appropriately implemented. However, the rest is familiar to me:

You have an end run with no opening on run declaration. The script still compiles and executes, but won’t return a value should one be required. Your options here are either:

  • to insert on run at the start of your Stage 1 script and leave end run as it is;

or:

  • to delete end run.

The effect of either decision ought to be identical in this case, which is for the script to return the value of the selected list option.

If you don’t particularly need the script to throw an error in the situation a user presses cancel (which is a rather inelegant means of ending a script’s run), then a slightly more streamlined version of Stage 1 might look like this:

set PhotoshopActionList to {"Action1", "Action2", "Action3", "Action4", "Action5"}

set [ActionrequiredAnswer] to {} & (choose from list PhotoshopActionList ¬
	with title "Actions Picker" with prompt "Choose Action?")

ActionrequiredAnswer

which simply returns the chosen list option value, or false in the event of the user pressing Cancel. But your version as it is currently implemented is just as good, bar the correction recommended above.


It looks to me that if SourceFolder is already set, then there isn’t a problem with the script reaching the tell application "Finder" block. If, however, SourceFolder is a missing value, then your if...then...else clause catches it in the first instance in order to set the values of your two properties, then doesn’t progress to do anything further with them, so the script ends.

Making some assumptions on what I think the script should be doing, I would recommend keeping if...then, but terminating with end if immediately after that block, and omitted any else conditions. That is to say:

if SourceFolder = missing value then
    set SourceFolder to (choose folder with prompt "Choose Base Images:")
    set destinationFolder to (choose folder with prompt "Choose Save Location:")
end if

tell application "Finder"
   .
   .
   .
end tell

Onto the Finder block itself, I’m irked by your need to retrieve the entire contents of SourceFolder as list. As a side-note, it’s typically much quicker an operation if it’s coerced into an alias list instead of a list. Regardless of this, entire contents is a pretty expensive, slow operation for Finder to perform, as it performs a deep search of the folder, and the folders it contains, all the way down to the bottom. If that’s really what you need, and your directory tree isn’t very deep and each folder contains only a few files, then the operation may perform quickly enough to be viable. If your folders contain many items or have many levels of nested folders, you’ll quickly see a degradation in performance time, and might wish to think about using Objective-C to get a speedier result:

use framework "Foundation"
use scripting additions

property this : a reference to current application
property NSDirectoryEnumerationSkipsHiddenFiles : a reference to 4
property NSFileManager : a reference to NSFileManager of this

property SourceFolder : missing value
property destinationFolder : missing value

if SourceFolder = missing value then
	set SourceFolder to (choose folder with prompt "Choose Base Images:")
	set destinationFolder to (choose folder with prompt "Choose Save Location:")
end if

((NSFileManager's defaultManager()'s enumeratorAtURL:SourceFolder ¬
	includingPropertiesForKeys:[] ¬
	options:NSDirectoryEnumerationSkipsHiddenFiles ¬
	errorHandler:(missing value))'s allObjects()) as list

If, in fact, you do not need a deep search of a folder’s contents, and intended only to retrieve the items in the folder itself, presumably you are aware you can:

tell application "Finder"
	set theFolders to every item of SourceFolder as alias list
    .
    .
end tell

Since your choice of variable name theFolders suggests to me that you intend only to retrieve a list of folders, and not a list of files as well as folders, then:

tell application "Finder"
	set theFolders to every folder of SourceFolder as alias list
    .
    .
end tell

or, if the deep enumeration is needed:

tell application "Finder"
	set theFolders to every folder of entire contents of SourceFolder as alias list
    .
    .
end tell

or, by way of Objective-C (I’ve used Finder below to discriminate between files and folders in the returned list, but you could also use Objective-C’s NSFileTypeDirectory key to sort through the array, which I’ve not demonstrated here):

set entireContentsOfSourceFolder to ((NSFileManager's defaultManager()'s ¬
	enumeratorAtURL:SourceFolder includingPropertiesForKeys:[] ¬
		options:NSDirectoryEnumerationSkipsHiddenFiles ¬
		errorHandler:(missing value))'s allObjects()) as list

repeat with f in entireContentsOfSourceFolder
	set f's contents to f as alias
	tell application "Finder" to if item f's class ≠ folder then set f's contents to null
end repeat

set entireContentsOfSourceFolder to aliases of entireContentsOfSourceFolder

This clause:

files of entire contents of SourceFolder contains "_001", "_002", "003"

would—were it syntactically well-formed—return a value of type boolean, i.e. true if the entire contents of that folder contained those items; or false otherwise. In fact, because you enclosed the expression in braces, the syntax is functionally sound, but ends up providing you with a list of three items: the first being the boolean value I just described, and the second and third items being "002" and "003" in that order.

But your attempt to coerce it to an alias list, and store it in a variable called filesList suggests to me that you are seeking to obtain a list of files, and as best as I can tell, you’re hoping to retrieve a list of files with filenames containing any of those three suffixes (although reading back through your prose, there might actually be 14 suffixes to search for, which contain one additional leading zero than the two you included in your script). So, assuming that’s the case, I think you are looking for an expression more along these lines:

tell application "Finder"
	set filesList to (files of entire contents of SourceFolder whose ¬
		name ends with "_0000.tif" or ¬
		name ends with "_0001.tif" or ¬
		name ends with "_0002.tif" or ¬
		name ends with "_0003.tif" or ¬
		name ends with "_0004.tif" or ¬
		name ends with "_0005.tif" or ¬
		name ends with "_0006.tif" or ¬
		name ends with "_0007.tif" or ¬
		name ends with "_0008.tif" or ¬
		name ends with "_0009.tif" or ¬
		name ends with "_0010.tif" or ¬
		name ends with "_0011.tif" or ¬
		name ends with "_0012.tif" or ¬
		name ends with "_0013.tif") as alias list
end tell

As I initially forewarned, I can’t offer too much guidance with the Photoshop aspects of the script, but I can point out that your repeat loop is missing a corresponding end repeat. This is the type of error that you should have seen emerge at the point you tried to compile the script, which would have been explicit in what was missing, allowing you to correct it. It’s best to correct what you know to be an obvious error before you start to wonder why the bigger objective isn’t being achieved.


I’ve assumed by how you presented your script in stages together with syntax clues that each script is designed to run separately. But, having combed through it all with you, it seems to me to make more sense were the entire thing to be executed as a single script. Sorry, this may have been my sleepy brain not registering the obvious. Anyway, here’s a summary of what a single script might end up looking like if you implemented my suggested changes:

property SourceFolder : missing value
property destinationFolder : missing value

-- Obtain user choice of PS action
set PhotoshopActionList to {"Action1", "Action2", "Action3", "Action4", "Action5"}
set [ActionrequiredAnswer] to {} & (choose from list PhotoshopActionList ¬
	with title "Actions Picker" with prompt "Choose Action?")

-- If user cancels, then terminate the script
if ActionrequiredAnswer = false then return false


if SourceFolder = missing value then
	set SourceFolder to (choose folder with prompt "Choose Base Images:")
	set destinationFolder to (choose folder with prompt "Choose Save Location:")
end if

tell application "Finder"
	-- Get every FOLDER within the SourceFolder subtree
	set theFolders to every folder of entire contents of SourceFolder as alias list
	
	repeat with thisFolder in theFolders
		make new alias file at destinationFolder to thisFolder
	end repeat
	
	-- Get every FILE within the SourceFolder subtree and filter to
	-- include only files with names ending in specific suffixes 
	set filesList to (files of entire contents of SourceFolder whose ¬
		name ends with "_0000.tif" or ¬
		name ends with "_0001.tif" or ¬
		name ends with "_0002.tif" or ¬
		name ends with "_0003.tif" or ¬
		name ends with "_0004.tif" or ¬
		name ends with "_0005.tif" or ¬
		name ends with "_0006.tif" or ¬
		name ends with "_0007.tif" or ¬
		name ends with "_0008.tif" or ¬
		name ends with "_0009.tif" or ¬
		name ends with "_0010.tif" or ¬
		name ends with "_0011.tif" or ¬
		name ends with "_0012.tif" or ¬
		name ends with "_0013.tif") as alias list
end tell

I omitted the final parts for reasons already stated, but regarding Stage 4, I ought to point out that the variable currentDocument is undefined, which will throw an error during execution. Perhaps the entire line belongs inside a Photoshop block, which, if scriptable, likely contains a document object, where document 1 or front document almost always refer to the document open in the application that currently has focus, which might be a good substitute (or value) for your currentDocument.

Finally, returning to Stage 3, I spotted the use of "Action 1" in the line that starts do action..., and wonder if this is where you want to replace that string with your earlier-defined, but somewhat oddly-named, variable ActionrequiredAnswer ?


(Ed Stockly) #3

This is pretty easy to do. You’d start with a list of action names {“Action1”,“Action2”,“Actionx”}
then use the “Choose from list” command from the standard additions.

Use the Choose folder command from Standard additions

Is this an existing folder or a new folder? Either way, use the chose folder command and you may use the “New” button in the dialog.

This would use photoshop’s “Do Action” command:
do action “action 1” from “My Actions” – The name of the action and the action set

Use the photoshop save command.


#4

This is Brilliant!!! exactally what i needed, thank you so much!!!