Skip to main content
Known Participant
April 17, 2024
Answered

Photoshop script replacing linked smart objects based on layer "name string"

  • April 17, 2024
  • 3 replies
  • 2648 views

I need a photoshop script to do the following:

Open a Dialogue Box and have an option to...
 Replace linked smart objects labeled "RED" in the Name of the layer and update all linked smart objects associated with that color to "BLUE"
ex: "RED" will replace the following smart objects based on their name from the current file directory

Linked Smart Objects:
- RED_3D22
- RED_BLACK
- RED_FUTURE
- RED_WHITE
- RED_HUGOKNOTS_NEG
- RED_HUGOKNOTS_POS
- RED_MONOCHROME
- RED_MONOPLUS_BP

to these Linked Smart Objects from the same directory

- BLUE_3D22
- BLUE_BLACK
- BLUE_FUTURE
- BLUE_WHITE
- BLUE_HUGOKNOTS_NEG
- BLUE_HUGOKNOTS_POS
- BLUE_MONOCHROME
- BLUE_MONOPLUS_BP

 

** If smart object above does not exist in the existing PSD, it will ignore and continue executing the script til completion.

that is all, no exporting or saving, just swapping.

any help is appreciated.

This topic has been closed for replies.
Correct answer Stephen Marsh

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);
            }
        }
    }
}

 

 

 

3 replies

Stephen Marsh
Stephen MarshCorrect answer
Community Expert
April 19, 2024

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);
            }
        }
    }
}

 

 

 

Known Participant
April 19, 2024

First of all, thank you for your reply and attempt at this.

While the script works, I am trying to have it look for instances for a replacement of all smart objects.

example, imagine the folder has "GREEN_CIRCLE", or "PURPLE" CIRCLE, etc. Ideally I would like to 

have the script locate the directory and replace the prefix name along with what type of object it is.

ex:

script would search "red" and identify any object labeled "red" and replace objects based on

the remaining string (_circle, or _square) 

I am going to build a PSD that will have over 20 smart objects, and would like to auto replace in 1 swoop

rather than having to manually select the replacements. so basically all smart objects will have the same ending text, only change would be the text aka red, green, blue, purple, etc etc.

if that is possible of course.

Thank you in advance!

Stephen Marsh
Community Expert
April 25, 2024

Let me see if I can explain this differently.

These are the 4 linked smart objects in the PSD labeled the following:


AWAY_TEAM_NAME.psd

AWAY_TEAM_LOGO.psd

HOME_TEAM_NAME.psd

HOME_TEAM_LOGO.psd

 

I would like to have the script target and replace the 4 Smart Objects based on the first part of the name,


AWAY_TEAM_NAME.psd <-- script replaces this based on the name "AWAY" to "PIGS"

AWAY_TEAM_LOGO.psd <-- same as above

HOME_TEAM_NAME.psd <-- script replaces this based on the name "HOME" to "SLOTHS"

HOME_TEAM_LOGO.psd <-- same as above


** I still want to keep the functionality that looks for the part of the name "_TEAM_NAME" and "_TEAM_LOGO" since I can add an infinite amount
of smart objects as long as they have the same text string that is identified by the "HOME" and "AWAY" portion,

If I needed to create high school sports matchups for example and have a list of multiple teams, it be easier to type out the team name(s) and
replace that way instead of the script replacing "ALL" smart objects.

 

I can rename the default smart object layers to "AWAY_TEAM_NAME" / "AWAY_TEAM_LOGO" and "HOME_TEAM_NAME" / "HOME_TEAM_LOGO"

Again, thank you for your help, I know this can be quite the headache so any help is extremely appreciated.


So, at the moment you would run the script twice:

 

Once for:

  • AWAY_TEAM_NAME.psd
  • AWAY_TEAM_LOGO.psd

 

Replacing AWAY for PIGS

 

Then a second time for:

  • HOME_TEAM_NAME.psd
  • HOME_TEAM_LOGO.psd

 

Replacing HOME for SLOTHS

 

However, you would like to automate that further? The script would need to find the different name prefixes, and then offer a new prefix to swap out for the replacements.

Stephen Marsh
Community Expert
April 19, 2024

@defaulttev3kfc5iehr 

 

You can try the following "Relink Top-Level Smart Object Layers Using New Name Prefix.jsx" script:

 

/*
Relink Top-Level Smart Object Layers Using New Name Prefix.jsx
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 Top-Level Smart Object Layers Using New Name Prefix.jsx", "main()");

function main() {

  (function () {

    try {

      // Prompt for the colour prefix
      var thePrefix = prompt("Enter the new linked filename prefix:", "red");
      if (thePrefix === null) {
        //alert('Script cancelled!');
        //app.beep();
        return
      }

      // Loop over the root/top-level layer (not groups or the content of nested groups)
      for (var i = 0; i < app.activeDocument.artLayers.length; i++) {
        activeDocument.activeLayer = activeDocument.artLayers[i];
        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');
            var theName = getSmartObjectReference().filePath.fsName.toString().replace(/(^.+?)(_.+)/, '$2');
            var theAD = new ActionDescriptor();
            // Relink to the new file 
            theAD.putPath(stringIDToTypeID("null"), new File(thePath + thePrefix + theName));
            executeAction(stringIDToTypeID("placedLayerRelinkToFile"), theAD, DialogModes.NO);
          }
        }
      }

      // End of script notification
      app.beep();

    } catch (e) {
      alert("Error!" + "\r" + e + ' ' + e.line);
    }


    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;
      }
    }

  })();

}

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

Stephen Marsh
Community Expert
April 17, 2024

Sample files (low resolution) or at least a screenshot of the layers panel and the properties panel for a selected layer would help others to help you.

Known Participant
April 17, 2024

Hopefully this explains it, simplified the request, basically looking to have a dialogue box open to replace linked smart object instances of the "like" layers. at once instead of having to repeat the process.