This "Relink All Smart Object Layers Using New Name Prefix.jsx" variation will process all linked smart object layers found inside layer groups/nested layer groups (not only root/top-level layers):
/*
Relink All Smart Object Layers Using New Name Prefix.jsx
(Including layers in groups and nested groups)
v1.0 - 19th April 2024, Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/photoshop-script-replacing-linked-smart-objects-based-on-layer-quot-name-string-quot/td-p/14559920
Note: The case-insensitive colour name prefix replaces the linked file with another file in the same directory with a different colour prefix name -
From: blue_rectangle.psd
blue_circle.psd
To: red_rectangle.psd
red_circle.psd
There is no need to type the underscore _ separator character (although it has to exist in the filename) and the replacement image should have the same resolution and file format as the smart objects
*/
#target photoshop
app.activeDocument.suspendHistory("Relink All Smart Object Layers Using New Name Prefix.jsx", "main()");
function main() {
// Prompt for the colour prefix
var thePrefix = prompt("Enter the new linked filename prefix:", "red");
if (thePrefix === null) {
//alert('Script cancelled!');
//app.beep();
return
}
processAllLayersAndSets(app.activeDocument);
///// FUNCTIONS /////
function getSmartObjectReference() {
// https://stackoverflow.com/questions/63010107/get-a-smart-objects-layers-files-directory-source-in-jsx
try {
var smartObject = {
found: false,
fileRef: '',
filePath: '',
linked: false,
};
var ref, so;
ref = new ActionReference();
ref.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("smartObject"));
ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
so = executeActionGet(ref).getObjectValue(stringIDToTypeID("smartObject"));
smartObject.found = true;
smartObject.linked = so.getBoolean(stringIDToTypeID("linked"));
smartObject.fileRef = so.getString(stringIDToTypeID("fileReference"));
if (smartObject.linked) {
smartObject.filePath = so.getPath(stringIDToTypeID("link"));
} else {
smartObject.filePath = Folder.temp + '/' + smartObject.fileRef;
}
return smartObject;
} catch (e) {
alert(e);
return smartObject;
}
}
function processAllLayersAndSets(obj) {
// Process all layers and layer sets
// Change the following 2 entries of "obj.artLayers" to "obj.layers" to include layer sets
for (var al = obj.artLayers.length - 1; 0 <= al; al--) {
app.activeDocument.activeLayer = obj.artLayers[al];
relink();
}
// Process Layer Set Layers
for (var ls = obj.layerSets.length - 1; 0 <= ls; ls--) {
processAllLayersAndSets(obj.layerSets[ls]);
relink();
}
}
function relink() {
if (app.activeDocument.activeLayer.kind == LayerKind.SMARTOBJECT) {
// Conditional check for linked SO
var ref = new ActionReference();
ref.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("smartObject"));
ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
var so = executeActionGet(ref).getObjectValue(stringIDToTypeID("smartObject"));
if (so.getBoolean(stringIDToTypeID("linked"))) {
// Set the file path and name variables
var thePath = getSmartObjectReference().filePath.toString().replace(/(^.+\/)(.+)/, '$1');
//alert(thePath);
var theName = getSmartObjectReference().filePath.fsName.toString().replace(/(^.+?)(_.+)/, '$2');
//alert(theName);
var theAD = new ActionDescriptor();
//alert((thePath + thePrefix + theName));
// Relink to the new file
theAD.putPath(stringIDToTypeID("null"), new File(thePath + thePrefix + theName));
executeAction(stringIDToTypeID("placedLayerRelinkToFile"), theAD, DialogModes.NO);
}
}
}
}