Skip to main content
dunazee
Inspiring
September 18, 2026
Question

how to duplicate a layer with a linked file and link it to something else?

  • September 18, 2026
  • 6 replies
  • 44 views

Is there an easier way to duplicate a linked layer and unlink it from the original link so I can re-link that one instance to something else?

Right now I’m duplicating the layer, making a smart object, and then double clicking into the smart object and re-linking. So every time my linked file changes, I have to go individually into each smart layer to update the link. Kind of a PITA.

 

Back-story: making mockups of different label interations on the same package rendering (today, a bag of frozen chicken wings, woo hoo!). In this case, I’ve got all my labels in one Ps file and then turning on one layer at a time to export them as PNGs to place into a presentation document (Illustrator). Another way I sometimes do it is to create a separate Ps file for each instance of a link, but then I still have to open each file to update the link… 

 

Can I do something like this if I use artboards in Ps instead of just layers? I’d like to be able to open a file, have all the links update, and then export in one fell swoop. Totally open to suggestions, thanks! 

 

Mac OS 26.6.2, PS 27.10.0

 

    6 replies

    Stephen Marsh
    Community Expert
    Community Expert
    September 19, 2026

    Relink to New Linked Smart Object via Copy.jsx is a related script, which links to a different existing file, rather than creating a new copy of the current linked file. This is only mentioned as it's related, the previous New Linked Smart Object via Copy (v1.2) is the one that you are looking for. EDIT: It might work for you if you duplicated the active layer first.

     

    /*
    Relink to New Linked Smart Object via Copy.jsx
    v1.0 - 9th September 2024, Stephen Marsh
    NOTE: The script will relink to an existing file
    https://community.adobe.com/t5/photoshop-ecosystem-discussions/please-fix-how-relink-to-file-and-replace-content-work/td-p/14846535
    Related to:
    https://community.adobe.com/t5/photoshop-ecosystem-discussions/why-is-new-smart-object-via-copy-greyed-out-for-linked-smart-objects/td-p/14371680
    */

    #target photoshop

    try {

    // Smart object action manager properties
    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"));

    // Conditional check for the active layer being a linked smart object
    if (so.getBoolean(stringIDToTypeID("linked"))) {
    // Single history stage undo
    activeDocument.suspendHistory("Relink to New Linked Smart Object via Copy.jsx", "main()");
    }

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

    function main() {

    try {

    // Convert the active linked smart object layer to an embedded smart object
    executeAction(stringIDToTypeID("newPlacedLayer"), undefined, DialogModes.NO);

    // Edit the smart object contents
    executeAction(stringIDToTypeID("placedLayerEditContents"), new ActionDescriptor(), DialogModes.NO);

    // Relink to file
    var idselect = stringIDToTypeID("select");
    var desc350 = new ActionDescriptor();
    var idnull = stringIDToTypeID("null");
    var ref59 = new ActionReference();
    var idmenuItemClass = stringIDToTypeID("menuItemClass");
    var idmenuItemType = stringIDToTypeID("menuItemType");
    var idplacedLayerRelinkToFile = stringIDToTypeID("placedLayerRelinkToFile");
    ref59.putEnumerated(idmenuItemClass, idmenuItemType, idplacedLayerRelinkToFile);
    desc350.putReference(idnull, ref59);
    executeAction(idselect, desc350, DialogModes.ALL);

    // Get the layer name
    var layerName = app.activeDocument.activeLayer.name;

    // Close and save
    app.activeDocument.close(SaveOptions.SAVECHANGES);

    // Convert the embedded smart object back to a linked smart object
    executeAction(stringIDToTypeID("placedLayerConvertToLayers"), undefined, DialogModes.NO);

    // Set the layer name
    app.activeDocument.activeLayer.name = layerName;

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

    }

     

    Stephen Marsh
    Community Expert
    Community Expert
    September 18, 2026

    @dunazee 

     

    New Linked Smart Object via Copy (v1.2) duplicates the original linked smart object into a new layer that points to a new file on disk, a copy of the original. The two linked layer objects can then be edited independently.

     

    /*
    New Linked Smart Object via Copy.jsx
    Stephen Marsh
    https://community.adobe.com/t5/photoshop-ecosystem-discussions/why-is-new-smart-object-via-copy-greyed-out-for-linked-smart-objects/td-p/14371680

    v1.0 - 25th January 2024:
    Initial release.

    v1.1 - 27th January 2024:
    Added filename validation so as not to overwrite an existing file.

    v1.2 - 19th September 2026:
    If the replacement file already exists, the user is prompted for a new name
    (validated, re-prompted until valid) instead of the script cancelling.
    Cancelling the prompt exits cleanly without changes.
    */

    #target photoshop

    // Smart object action manager properties
    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"));

    // Conditional check for the active layer being a linked smart object
    if (so.getBoolean(stringIDToTypeID("linked"))) {
    // Single history stage undo
    activeDocument.suspendHistory("New Linked Smart Object via Copy.jsx", "main()");
    }

    function main() {

    // Doc path, name and extension variables
    var thePath = so.getPath(stringIDToTypeID("link")).fullName.replace(/(^.+\/)(.*)/, '$1');
    var theName = so.getString(stringIDToTypeID("fileReference")).replace(/\.[^\.]+$/, '');
    var theExt = so.getString(stringIDToTypeID("fileReference")).replace(/(.+)(\.[^\.]+$)/, '$2');

    // Default copy filename
    var copyName = theName + " copy";

    // Check for filename clashes and allow the user to enter a new filename
    var theCopy = new File(thePath + copyName + theExt);

    if (theCopy.exists) {

    var validName = false;

    while (!validName) {

    var newName = prompt(
    'The file "' + copyName + theExt + '" already exists.\n\n' +
    'Enter a new filename:',
    copyName
    );

    // Cancel
    if (newName === null) {
    return;
    }

    // Remove leading/trailing spaces
    newName = newName.replace(/^\s+|\s+$/g, '');

    // Validate filename
    if (newName === '') {
    alert('Filename cannot be blank.');
    continue;
    }

    // Remove extension if the user entered the original extension
    var extRegex = new RegExp('\\' + theExt + '$', 'i');
    if (extRegex.test(newName)) {
    newName = newName.replace(extRegex, '');
    }

    // Check for invalid Windows filename characters
    if (/[\\\/:\*\?"<>\|]/.test(newName)) {
    alert(
    'The filename contains invalid characters.\n\n' +
    'The following characters are not allowed:\n' +
    '\\ / : * ? " < > |'
    );
    continue;
    }

    // Prevent the new filename from matching the original
    if (newName.toLowerCase() === theName.toLowerCase()) {
    alert(
    'The new filename cannot be the same as the original filename.'
    );
    continue;
    }

    // Check whether the new filename already exists
    theCopy = new File(thePath + newName + theExt);

    if (theCopy.exists) {
    alert(
    'The file "' + newName + theExt + '" already exists.\n\n' +
    'Please enter a different filename.'
    );
    copyName = newName;
    continue;
    }

    // Filename is valid and available
    copyName = newName;
    validName = true;
    }
    }

    // Final copy file
    theCopy = new File(thePath + copyName + theExt);

    // Duplicate the linked file
    if (!new File(thePath + theName + theExt).copy(theCopy.fsName)) {
    alert(
    'Unable to create the copied file:\n\n' +
    theCopy.fsName
    );
    return;
    }

    // Set the references to the original doc name and original layer ID
    var origDocName = activeDocument.name;
    var origLayerID = activeDocument.activeLayer.id;

    // Attempt to unlock the layer before it is duplicated to the temp doc
    try {
    unlockActiveLayer();
    } catch (e) {}

    // Dupe the smart object layer to a new temp doc
    var descriptor = new ActionDescriptor();
    var reference = new ActionReference();
    var reference2 = new ActionReference();
    reference.putClass(s2t("document"));
    descriptor.putReference(s2t("null"), reference);
    descriptor.putString(s2t("name"), "tempDoc");
    reference2.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
    descriptor.putReference(s2t("using"), reference2);
    descriptor.putString(s2t("layerName"), activeDocument.activeLayer.name);
    executeAction(s2t("make"), descriptor, DialogModes.NO);

    // Relink to the duplicated file copy
    var idplacedLayerRelinkToFile = stringIDToTypeID("placedLayerRelinkToFile");
    var desc15 = new ActionDescriptor();
    var idnull = stringIDToTypeID("null");
    desc15.putPath(idnull, theCopy);
    executeAction(idplacedLayerRelinkToFile, desc15, DialogModes.NO);

    // Dupe the relinked temp doc layer back to the original doc
    var descriptor2 = new ActionDescriptor();
    var reference3 = new ActionReference();
    var reference4 = new ActionReference();
    reference3.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
    descriptor2.putReference(s2t("null"), reference3);
    reference4.putName(s2t("document"), origDocName);
    descriptor2.putReference(s2t("to"), reference4);
    descriptor2.putString(s2t("name"), activeDocument.activeLayer.name);
    executeAction(s2t("duplicate"), descriptor2, DialogModes.NO);

    // Close the temp doc (still the active doc), which returns focus to the original doc
    activeDocument.close(SaveOptions.DONOTSAVECHANGES);

    // The new relinked layer is now the active layer in the original doc, store its ID
    var newLayerID = activeDocument.activeLayer.id;

    // Select the original (previous) layer in the stack
    try {
    selectLayerByID(origLayerID);
    } catch (e) {
    alert('Unable to select the original layer:\n\n' + e.message);
    return;
    }

    /*
    // Delete the now redundant original layer (already unlocked above)
    try {
    app.activeDocument.activeLayer.remove();
    } catch (e) {
    alert(
    'Unable to delete the original layer. It may still be locked.\n\n' +
    e.message
    );
    }
    */

    // Reselect the new relinked layer
    try {
    selectLayerByID(newLayerID);
    } catch (e) {
    // Selection is left as-is
    }
    }


    ///// Functions /////

    function s2t(s) {
    return app.stringIDToTypeID(s);
    }

    function selectLayerByID(id) {
    var desc = new ActionDescriptor();
    var ref = new ActionReference();
    ref.putIdentifier(s2t("layer"), id);
    desc.putReference(s2t("null"), ref);
    desc.putBoolean(s2t("makeVisible"), false);
    executeAction(s2t("select"), desc, DialogModes.NO);
    }

    function unlockActiveLayer() {
    var lyr = activeDocument.activeLayer;
    var locked = false;

    try {
    if (lyr.allLocked || lyr.pixelsLocked || lyr.positionLocked || lyr.transparentPixelsLocked) {
    locked = true;
    }
    } catch (e) {
    // Lock state could not be read, attempt the unlock anyway
    locked = true;
    }

    if (!locked) {
    return;
    }

    try {
    lyr.allLocked = false;
    } catch (e) {}
    try {
    lyr.pixelsLocked = false;
    } catch (e) {}
    try {
    lyr.positionLocked = false;
    } catch (e) {}
    try {
    lyr.transparentPixelsLocked = false;
    } catch (e) {}
    }

    function deleteActiveLayer() {
    var desc = new ActionDescriptor();
    var ref = new ActionReference();
    ref.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
    desc.putReference(s2t("null"), ref);
    executeAction(s2t("delete"), desc, DialogModes.NO);
    }

     

    1. Copy the code text to the clipboard
    2. Open a new blank file in a plain-text editor (not in a word processor)
    3. Paste the code in
    4. Save as a plain text format file – .txt
    5. Rename the saved file extension from .txt to .jsx
    6. Install or browse to the .jsx file to run (see below)
    Stephen Marsh
    Community Expert
    Community Expert
    September 18, 2026

    I wrote a script to automate this, let me dig it up…

    Conrad_C
    Community Expert
    Community Expert
    September 18, 2026

    (I edited this reply because my original answer wasn’t quite correct)

    If you’re duplicating a linked Smart Object using any of the shortcuts for the command Layer > New Layer via Copy, then all copies point to the same linked file.

    If it was embedded you could try the command Layer > Smart Objects > New Smart Object via Copy, which would disconnect the link from the original, but for some reason that command is unavailable for linked files. So you may have to continue with your workarounds. Artboards won’t make a difference.

    A possibly better workaround is to use frames instead. For each different label, use the Frame tool to draw a frame placeholder for it of the correct dimensions. Then drop each imported file into the frame sized and positioned for it. Because the frames started out independently, their file links won’t be connected. You can replace the contents of any selected frame at any time by simply dragging a different image file from the desktop or other drag source such as Adobe Bridge, and dropping it on the frame (a shortcut for the command Layer > Smart Objects > Relink to File).

    dunazee
    dunazeeAuthor
    Inspiring
    September 18, 2026

    I’ll read up on that, thanks. I don’t want to embed the file, although I see the allure. I want to have one single source of truth, so to speak, so I’m only revising the one file that’s linked to many others.

    Illustrator now has the option to re-link one or all instances, which is handy. I’d definitely use something like that in Ps if it were there. I lay out my conceptual labels in Ai at 100% (to get the spatial proportions correct), ideally on the correct die line, and then place those labels in Ai and Ps. 

    Anyway, thanks for the tip, I’ll check it out.