I put together a script to rename the (single) selected layer in Photoshop .
tell application id "com.adobe.Photoshop"
activate
try
set currentDocument to the current document
on error
display dialog "No document open in Photoshop. ¬
Nothing to do." giving up after 3 buttons {"Ok"}
return
end try
tell currentDocument
set newLayerName to "This is the new name"
set selectedLayer to (get current layer)
set name of selectedLayer to newLayerName
end tell
end tell
It works fine, and now I’m trying to make a new one that would rename multiple selected layers. Here’s what I’ve tried, but I’m pretty bad with AppleScript & haven’t managed to get to work.
tell application id "com.adobe.Photoshop"
activate
try
set currentDocument to the current document
on error
display dialog "No document open in Photoshop. ¬
Nothing to do." giving up after 3 buttons {"Ok"}
return
end try
tell currentDocument
set newLayerName to "This is the new name"
set selectedLayers to (get layers as list)
repeat with thisLayer in selectedLayers
set thisLayer to (get current layer)
set name of thisLayer to clipboardName
end repeat
end tell
end tell
This one gets tricky fast because Photoshop doesn’t give Applescript access to the selected layers.
The selected layers can be retrieved by name or index via Javascript Action Manager code.
This quick script works in a limited way:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
set selectedLayers to get_PS_layer_names()
set repeatCount to 0
tell application "/Applications/Adobe Photoshop CS6/Adobe Photoshop CS6.app"
set currentDoc to the current document
tell currentDoc
repeat with aLayer in selectedLayers
set repeatCount to repeatCount + 1
set the name of layer aLayer to ("New Name " & repeatCount)
end repeat
end tell
end tell
on get_PS_layer_names()
tell application "Adobe Photoshop CS6"
tell the current document
set selectedLayers to paragraphs of (do javascript "
var typeDocument = stringIDToTypeID('document');
var typeItemIndex = stringIDToTypeID('itemIndex');
var typeLayer = stringIDToTypeID('layer');
var typeName = stringIDToTypeID('name');
var typeOrdinal = stringIDToTypeID('ordinal');
var typeProperty = stringIDToTypeID('property');
var typeTarget = stringIDToTypeID('targetEnum');
var typeTargetLayers = stringIDToTypeID('targetLayers');
var selectedLayers = new Array();
var actionRef = new ActionReference();
actionRef.putEnumerated(typeDocument, typeOrdinal, typeTarget);
var actionDesc = executeActionGet(actionRef);
if(actionDesc.hasKey(typeTargetLayers) ){
actionDesc = actionDesc.getList(typeTargetLayers);
var c = actionDesc.count
for(var i=0;i<c;i++){
try{
activeDocument.backgroundLayer;
selectedLayers.push(actionDesc.getReference( i ).getIndex() );
}catch(e){
selectedLayers.push(actionDesc.getReference( i ).getIndex()+1 );
}
}
}else{
var actionRef = new ActionReference();
actionRef.putProperty(typeProperty , typeItemIndex);
actionRef.putEnumerated(typeLayer, typeOrdinal, typeTarget);
try{
activeDocument.backgroundLayer;
selectedLayers.push( executeActionGet(actionRef).getInteger(typeItemIndex)-1);
}catch(e){
selectedLayers.push( executeActionGet(actionRef).getInteger(typeItemIndex));
}
}
var selectedLayerNames = new Array();
for (var a in selectedLayers){
var ref = new ActionReference();
ref.putIndex(typeLayer, Number(selectedLayers[a]) );
var layerName = executeActionGet(ref).getString(typeName);
selectedLayerNames.push(layerName);
}
selectedLayerNames.join('\\n');
")
end tell
end tell
end get_PS_layer_names
But it fails if any of the selected layers are grouped (inside a layer set), or if any of the selected layers already have the same name when the script is run.
Using Action Manager code to get the selected layers by index and using index to target them for renaming would probably be a lot better, but I couldn’t quickly google up the AM code to return the indexes of the selected layers, and I’m not good enough with AM code to write that.
Maybe this works for your needs?
I didn’t know what you wanted to use for the new layer names. Your “clipboardName” variable is undefined.
Here’s a version that renames all selected layers, regardless of how they’re nested into layer sets, and it doesn’t matter if there are layers with duplicate names.
Note: I was tired and couldn’t immediately figure out how to do this with a single repeat loop to handle both the initial layer set of the whole document, and the lower level layer sets, in the recursive function. So it’s two functions, which seemed a little redundant as I was writing it. After writing it, I realized I just need to always feed a list of layers into the function, never a single “layer set” as the input. So it could be re-written to be significantly more elegant but… eh, it’s late, and it works. Maybe I’ll fix it later.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
global foundLayer
set foundLayer to false
set selectedLayerIndexes to get_selected_layer_indexes()
set selectedLayerReferences to {}
repeat with aLayerIndex in selectedLayerIndexes
copy find_layer_by_itemindex(aLayerIndex) to end of selectedLayerReferences
end repeat
tell application "/Applications/Adobe Photoshop CS6/Adobe Photoshop CS6.app"
set currentDoc to the current document
tell currentDoc
set repeatCount to 0
repeat with i from (count of selectedLayerReferences) to 1 by -1
set aLayer to item i of selectedLayerReferences
set repeatCount to repeatCount + 1
set the name of aLayer to ("New Name " & repeatCount)
end repeat
end tell
end tell
on find_layer_by_itemindex(theItemIndex)
set theItemIndex to theItemIndex as number
tell application "/Applications/Adobe Photoshop CS6/Adobe Photoshop CS6.app"
set currentDoc to the current document
tell currentDoc
set layerCount to count of the layers
repeat with i from 1 to layerCount
set aLayer to layer i
if the itemindex of aLayer is theItemIndex then
return aLayer
else
if class of aLayer is layer set then
set foundLayer to false
set layerReturned to my recurse_layer_sets(aLayer, theItemIndex)
if layerReturned ≠ false then return layerReturned
end if
end if
end repeat
end tell
end tell
end find_layer_by_itemindex
on recurse_layer_sets(layerSet, theItemIndex)
if foundLayer ≠ false then return foundLayer
tell application "/Applications/Adobe Photoshop CS6/Adobe Photoshop CS6.app"
set currentDoc to the current document
tell currentDoc
set layersetCount to the count of the layers of layerSet
repeat with i from 1 to layersetCount
set aLayer to layer i of layerSet
if the itemindex of aLayer as number is theItemIndex then
set foundLayer to aLayer
exit repeat
else
if the class of aLayer is layer set then my recurse_layer_sets(aLayer, theItemIndex)
end if
end repeat
return foundLayer
end tell
end tell
end recurse_layer_sets
on get_selected_layer_indexes()
tell application "/Applications/Adobe Photoshop CS6/Adobe Photoshop CS6.app"
set selectedLayers to do javascript "
getSelectedLayersIdx()
function getSelectedLayersIdx() {
var selectedLayers = new Array;
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID(\"Dcmn\"), charIDToTypeID(\"Ordn\"), charIDToTypeID(\"Trgt\"));
var desc = executeActionGet(ref);
if (desc.hasKey(stringIDToTypeID(\"targetLayers\"))) {
desc = desc.getList(stringIDToTypeID(\"targetLayers\"));
var c = desc.count
var selectedLayers = new Array();
for (var i = 0; i < c; i++) {
try {
docRef.backgroundLayer;
selectedLayers.push(desc.getReference(i).getIndex());
} catch (e) {
selectedLayers.push(desc.getReference(i).getIndex() + 1);
}
}
} else {
var ref = new ActionReference();
ref.putProperty(charIDToTypeID(\"Prpr\"), charIDToTypeID(\"ItmI\"));
ref.putEnumerated(charIDToTypeID(\"Lyr \"), charIDToTypeID(\"Ordn\"), charIDToTypeID(\"Trgt\"));
try {
docRef.backgroundLayer;
selectedLayers.push(executeActionGet(ref).getInteger(charIDToTypeID(\"ItmI\")) - 1);
} catch (e) {
selectedLayers.push(executeActionGet(ref).getInteger(charIDToTypeID(\"ItmI\")));
}
}
return selectedLayers;
} "
end tell
return text_to_list(selectedLayers, ",")
end get_selected_layer_indexes
on text_to_list(someText, aSeparator)
set {delimitHolder, AppleScript's text item delimiters} to {AppleScript's text item delimiters, aSeparator}
set outputList to the text items of someText
set AppleScript's text item delimiters to delimitHolder
return outputList
end text_to_list
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
global foundLayer -- recursive function to drill down arbitrary layer nesting, setting global to exit function regardless of how deep the calls go
set selectedLayerIndexes to get_selected_layer_indexes() -- get the index numbers for all selected layers
set selectedLayerReferences to {}
tell application "/Applications/Adobe Photoshop CS6/Adobe Photoshop CS6.app" to tell the current document to set allLayers to the layers
-- convert each layer index to a layer reference
repeat with aLayerIndex in selectedLayerIndexes
set foundLayer to false
copy recurse_layer_sets(allLayers, aLayerIndex) to end of selectedLayerReferences
end repeat
-- rename each layer
tell application "/Applications/Adobe Photoshop CS6/Adobe Photoshop CS6.app"
set currentDoc to the current document
tell currentDoc
set repeatCount to 0
repeat with i from (count of selectedLayerReferences) to 1 by -1
set aLayer to item i of selectedLayerReferences
set repeatCount to repeatCount + 1
set the name of aLayer to ("New Name " & repeatCount)
end repeat
end tell
end tell
-- drills through all layer sets to look up layers by itemindex and return an Applescript reference to the layer
on recurse_layer_sets(layerList, theItemIndex)
set theItemIndex to theItemIndex as number -- it's already an integer; not sure why this is necessary
if foundLayer is not false then return foundLayer
tell application "/Applications/Adobe Photoshop CS6/Adobe Photoshop CS6.app"
set currentDoc to the current document
tell currentDoc
set layerGroupCount to the count of layerList
repeat with i from 1 to layerGroupCount
set aLayer to item i of layerList
if the (itemindex of aLayer) as number is theItemIndex then
set foundLayer to aLayer
exit repeat
else
if the class of aLayer is layer set then my recurse_layer_sets((layers of aLayer), theItemIndex)
end if
end repeat
end tell
end tell
return foundLayer
end recurse_layer_sets
-- AM code to get the indexes of all selected layers
on get_selected_layer_indexes()
tell application "/Applications/Adobe Photoshop CS6/Adobe Photoshop CS6.app"
set selectedLayers to do javascript "
getSelectedLayersIdx()
function getSelectedLayersIdx() {
var selectedLayers = new Array;
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID(\"Dcmn\"), charIDToTypeID(\"Ordn\"), charIDToTypeID(\"Trgt\"));
var desc = executeActionGet(ref);
if (desc.hasKey(stringIDToTypeID(\"targetLayers\"))) {
desc = desc.getList(stringIDToTypeID(\"targetLayers\"));
var c = desc.count
var selectedLayers = new Array();
for (var i = 0; i < c; i++) {
try {
docRef.backgroundLayer;
selectedLayers.push(desc.getReference(i).getIndex());
} catch (e) {
selectedLayers.push(desc.getReference(i).getIndex() + 1);
}
}
} else {
var ref = new ActionReference();
ref.putProperty(charIDToTypeID(\"Prpr\"), charIDToTypeID(\"ItmI\"));
ref.putEnumerated(charIDToTypeID(\"Lyr \"), charIDToTypeID(\"Ordn\"), charIDToTypeID(\"Trgt\"));
try {
docRef.backgroundLayer;
selectedLayers.push(executeActionGet(ref).getInteger(charIDToTypeID(\"ItmI\")) - 1);
} catch (e) {
selectedLayers.push(executeActionGet(ref).getInteger(charIDToTypeID(\"ItmI\")));
}
}
return selectedLayers;
} "
end tell
set selectedLayersListText to text_to_list(selectedLayers, ",") -- Javascript spits out comma delimited list
-- Javascript also spits out numbers as strings; switch to integers
set selectedLayersList to {}
repeat with anItem in selectedLayersListText
set selectedLayersList to selectedLayersList & (anItem as number)
end repeat
return selectedLayersList
end get_selected_layer_indexes
-- converts text delimited strings to AS lists
on text_to_list(someText, aSeparator)
set {delimitHolder, AppleScript's text item delimiters} to {AppleScript's text item delimiters, aSeparator}
set outputList to the text items of someText
set AppleScript's text item delimiters to delimitHolder
return outputList
end text_to_list
Thanks a lot for the help. So I guess I was way off with my attempts!
I tried the first one but got an error message:
error "Can’t set name of \"And this is the third layer\" to \"New Name 1\"." number -10006 from name of "And this is the third layer"
But the last version works great, just what I wanted! Thanks a lot!
Ah, this is the ‘proper’ variable that I’ll use quite often (set clipboardName to the clipboard). E.g. use the name copied to the clipboard to rename the selected layers in Photoshop.