Skip to main content
Participant
March 29, 2023
Answered

Need help to create script that stacks files with the same names together

  • March 29, 2023
  • 3 replies
  • 1140 views

Unfortunately I have little to know scripting knowledge so this is a bit out of my area of expertise for me.

 

I have 360 degree images and to remove the background easily I need a way to stack 3 files together. Normally I would do it manually but there are just too many files for this to be efficient.

 

Inside of each folder I have 3 subfolders, "spin" "spin2" and "spin3". In each folders the file names are the same.

 

I need help creating a script that stacks only similar file names together. So for example it would find in each of the folders "r010_a000.jpg", and put them in a layer stack.

 

Thanks in advance!

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

@djghost1133 

 

I quickly modified an older script from 2 to 3 input folders... I would do things slightly differently today, however, I don't have time at the moment. I'll look at refining the code later based on your feedback.

 

All it does is stack alphabetically sorting files from 3 input folders as a layered PSD. There is no error checking, it is presumed that all three input folders have the same number of files and that they are all named the same.

 

EDIT: Code updated to version 1.1:

 

/*
https://community.adobe.com/t5/photoshop-ecosystem-discussions/need-help-to-create-script-that-stacks-files-with-the-same-names-together/m-p/13688339
v1.1 - 30th March 2023, Stephen Marsh
Based on:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/auto-merge-files/m-p/10753387
*/

#target photoshop

var folder1 = Folder.selectDialog("Please select the 1st input folder");  // input folder 1
var folder2 = Folder.selectDialog("Please select the 2nd input folder");  // input folder 2 
var folder3 = Folder.selectDialog("Please select the 3rd input folder");  // input folder 3 

var saveFolder = Folder.selectDialog("Please select the folder to save to...");  // output folder
var searchMask = '*.???';
var list1 = folder1.getFiles(searchMask);
var list2 = folder2.getFiles(searchMask);
var list3 = folder3.getFiles(searchMask);
list1.sort(); // Alpha-numeric sort
list2.sort(); // Alpha-numeric sort
list3.sort(); // Alpha-numeric sort

app.displayDialogs = DialogModes.NO;

var psdOptions = new PhotoshopSaveOptions();
psdOptions.embedColorProfile = true;
psdOptions.alphaChannels = true;
psdOptions.layers = true;
psdOptions.spotColors = true;

for (var i = 0; i < list1.length; i++) {
    var doc = open(list1[i]);
    var docName = doc.name;
    activeDocument.activeLayer.name = folder1.name + " - " + docName.split('.')[0];
    placeFile(list2[i], 100);
    activeDocument.activeLayer.rasterize(RasterizeType.ENTIRELAYER);
    activeDocument.activeLayer.name = folder2.name + " - " + activeDocument.activeLayer.name;
    placeFile(list3[i], 100);
    activeDocument.activeLayer.rasterize(RasterizeType.ENTIRELAYER);
    activeDocument.activeLayer.name = folder3.name + " - " + activeDocument.activeLayer.name;
    doc.saveAs(new File(saveFolder + '/' + docName.split('.')[0] + '.psd'), psdOptions);
    doc.close(SaveOptions.DONOTSAVECHANGES);
};

alert('Script completed!' + '\n' + 'Files saved to:' + '\r' + saveFolder.fsName);

function placeFile(file, scale) {
    try {
        var idPlc = charIDToTypeID("Plc ");
        var desc2 = new ActionDescriptor();
        var idnull = charIDToTypeID("null");
        desc2.putPath(idnull, new File(file));
        var idFTcs = charIDToTypeID("FTcs");
        var idQCSt = charIDToTypeID("QCSt");
        var idQcsa = charIDToTypeID("Qcsa");
        desc2.putEnumerated(idFTcs, idQCSt, idQcsa);
        var idOfst = charIDToTypeID("Ofst");
        var desc3 = new ActionDescriptor();
        var idHrzn = charIDToTypeID("Hrzn");
        var idPxl = charIDToTypeID("#Pxl");
        desc3.putUnitDouble(idHrzn, idPxl, 0.000000);
        var idVrtc = charIDToTypeID("Vrtc");
        var idPxl = charIDToTypeID("#Pxl");
        desc3.putUnitDouble(idVrtc, idPxl, 0.000000);
        var idOfst = charIDToTypeID("Ofst");
        desc2.putObject(idOfst, idOfst, desc3);
        var idWdth = charIDToTypeID("Wdth");
        var idPrc = charIDToTypeID("#Prc");
        desc2.putUnitDouble(idWdth, idPrc, scale);
        var idHght = charIDToTypeID("Hght");
        var idPrc = charIDToTypeID("#Prc");
        desc2.putUnitDouble(idHght, idPrc, scale);
        var idAntA = charIDToTypeID("AntA");
        desc2.putBoolean(idAntA, true);
        executeAction(idPlc, desc2, DialogModes.NO);

    }
    catch (e) { }
}//end function placeFile

 

  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)

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

 

3 replies

Stephen Marsh
Community Expert
Community Expert
April 1, 2023

@djghost1133 

 

Here is an updated 1.3 version, you now only need to select the top-level/root folder containing the subfolders named "spin", "spin2" and "spin3" – rather than having to manually select all three spin folders.

 

/*
Stack 3 Input Folder Files to PSD.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/need-help-to-create-script-that-stacks-files-with-the-same-names-together/m-p/13688339
v1.3 - 1st March 2023, Stephen Marsh
*/

#target photoshop

// Set an action to process the stacked layers
var actionName = "Molten Lead"; // Action to run, change as needed
var actionSet = "Default Actions"; // Action set, change as needed

// app.documents.length === 0
if (!app.documents.length) {

    try {

        // Save and disable dialogs
        var restoreDialogMode = app.displayDialogs;
        app.displayDialogs = DialogModes.NO;

        // Main script function
        (function () {

            // Select the top-level/root folder
            var baseFolder = Folder.selectDialog('Please select the top-level/parent folder:');
            if (baseFolder === null) return;

            // Set the input folder paths from the top-level/root folder selection
            var inputFolder1 = Folder(baseFolder + "/" + "spin");
            var inputFolder2 = Folder(baseFolder + "/" + "spin2");
            var inputFolder3 = Folder(baseFolder + "/" + "spin3");

            // Limit the file format input, add or remove as required
            var fileList1 = inputFolder1.getFiles(/\.(png|jpe?g|tif?f|psd|psb)$/i);
            var fileList2 = inputFolder2.getFiles(/\.(png|jpe?g|tif?f|psd|psb)$/i);
            var fileList3 = inputFolder3.getFiles(/\.(png|jpe?g|tif?f|psd|psb)$/i);

            // Force alpha-numeric list sort
            fileList1.sort();
            fileList2.sort();
            fileList3.sort();

            // Validate that the file lists aren't empty
            var inputCount1 = fileList1.length;
            var cancelScript1 = (inputCount1 === 0);
            if (cancelScript1 === true) {
                alert('No input files found in the 1st folder, script cancelled!');
                return;
            }
            var inputCount2 = fileList2.length;
            var cancelScript2 = (inputCount2 === 0);
            if (cancelScript2 === true) {
                alert('No input files found in the 2nd folder, script cancelled!');
                return;
            }
            var inputCount3 = fileList3.length;
            var cancelScript3 = (inputCount3 === 0);
            if (cancelScript3 === true) {
                alert('No input files found in the 3rd folder, script cancelled!');
                return;
            }

            // Validate that the input folders have matching file list quantities
            if (inputCount2 !== inputCount1 || inputCount3 !== inputCount2) {
                alert('The input folders do not contain the same quantities of files, script cancelled!');
                return;
            }

            // Set the output folder
            var outputFolder = inputFolder1.parent;

            // or

            /*
            // Select the output folder
            var outputFolder = Folder.selectDialog("Please select the output folder:");
            if (outputFolder === null) {
                return;
            }
            */

            // Set the file processing counter
            var fileCounter = 0;

            // Open the files
            while (fileList1.length) {
                for (var a = 0; a < 1; a++) {
                    try {
                        app.open(fileList1.pop());
                        app.open(fileList2.pop());
                        if (app.documents[1].name != app.documents[0].name) {
                            alert('Name mismatch in the 2nd folder, script cancelled!');
                            return;
                        }
                        app.open(fileList3.pop());
                        if (app.documents[2].name != app.documents[0].name) {
                            alert('Name mismatch in the 3rd folder, script cancelled!');
                            return;
                        }
                    } catch (e) {}
                }

                // 1st doc
                app.activeDocument = documents[0];
                docNameToLayerName();
                activeDocument.activeLayer.name = inputFolder1.name + " - " + activeDocument.activeLayer.name;

                // Stack the 2nd and 3rd docs
                while (app.documents.length > 1) {
                    // 2nd doc
                    app.activeDocument = documents[1];
                    docNameToLayerName();
                    activeDocument.activeLayer.name = inputFolder2.name + " - " + activeDocument.activeLayer.name;
                    app.activeDocument.activeLayer.duplicate(documents[0]);
                    app.activeDocument = documents[0];
                    app.documents[1].close(SaveOptions.DONOTSAVECHANGES);
                    // 3rd doc
                    app.activeDocument = documents[1];
                    docNameToLayerName();
                    activeDocument.activeLayer.name = inputFolder3.name + " - " + activeDocument.activeLayer.name;
                    app.activeDocument.activeLayer.duplicate(documents[0]);
                    app.activeDocument = documents[0];
                    app.documents[1].close(SaveOptions.DONOTSAVECHANGES);
                }

                try {
                // Run the specified action on the stacked layers
                app.doAction(actionName, actionSet);
                } catch (e) {
                    e + ' ' + e.line;
                }

                // Save name & save path
                var docName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
                var saveFile = File(outputFolder + '/' + docName + '.psd');

                // Call the save function
                savePSD(saveFile);

                // Close all open files without saving
                while (app.documents.length) {
                    app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                }

                // Increment the file saving counter
                fileCounter++;


                ///// Functions /////

                function savePSD(saveFile) {
                    psdSaveOptions = new PhotoshopSaveOptions();
                    psdSaveOptions.embedColorProfile = true;
                    psdSaveOptions.alphaChannels = true;
                    psdSaveOptions.layers = true;
                    psdSaveOptions.annotations = true;
                    psdSaveOptions.spotColors = true;
                    app.activeDocument.saveAs(saveFile, psdSaveOptions, true, Extension.LOWERCASE);
                }

                function docNameToLayerName() {
                    var layerName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
                    app.activeDocument.activeLayer.name = layerName;
                }
            }

            // Restore saved dialogs
            app.displayDialogs = restoreDialogMode;

            // End of script notification
            app.beep();
            alert('Script completed!' + '\n' + fileCounter + ' combined files saved to:' + '\n' + outputFolder);

            // Open the output folder in the Finder or Explorer
            // outputFolder.execute();

        }());

    } catch (e) {
        // Restore saved dialogs
        app.displayDialogs = restoreDialogMode;
        alert("If you see this message, something went wrong!" + "\r" + e + ' ' + e.line);

    }
} else {
    alert('Please close all open documents before running this script!');
}

 

 

Stephen Marsh
Community Expert
Community Expert
March 31, 2023

@djghost1133 – Here is a refined 1.2 version (a total rewrite, including basic error checking at key points):

 

* Nominate an action set and action to play on the stacked layers.

 

* No need to set an output folder, the parent folder of the first input folder will be used as the save location

 

/*
Stack 3 Input Folder Files to PSD.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/need-help-to-create-script-that-stacks-files-with-the-same-names-together/m-p/13688339
v1.2 - 31st March 2023, Stephen Marsh
*/

#target photoshop

// Set an action to process the stacked layers
var actionName = "Molten Lead"; // Action to run, change as needed
var actionSet = "Default Actions"; // Action set, change as needed

// app.documents.length === 0
if (!app.documents.length) {

    try {

        // Save and disable dialogs
        var restoreDialogMode = app.displayDialogs;
        app.displayDialogs = DialogModes.NO;

        // Main script function
        (function () {

            // Select the input folders
            var inputFolder1 = Folder.selectDialog('Please select the 1st input folder:');
            if (inputFolder1 === null) return;
            var inputFolder2 = Folder.selectDialog('Please select the 2nd input folder:');
            if (inputFolder2 === null) return;
            var inputFolder3 = Folder.selectDialog('Please select the 3rd input folder:');
            if (inputFolder3 === null) return;

            // Limit the file format input, add or remove as required
            var fileList1 = inputFolder1.getFiles(/\.(png|jpe?g|tif?f|psd|psb)$/i);
            var fileList2 = inputFolder2.getFiles(/\.(png|jpe?g|tif?f|psd|psb)$/i);
            var fileList3 = inputFolder3.getFiles(/\.(png|jpe?g|tif?f|psd|psb)$/i);

            // Force alpha-numeric list sort
            fileList1.sort();
            fileList2.sort();
            fileList3.sort();

            // Validate that the file lists aren't empty
            var inputCount1 = fileList1.length;
            var cancelScript1 = (inputCount1 === 0);
            if (cancelScript1 === true) {
                alert('No input files found in the 1st folder, script cancelled!');
                return;
            }
            var inputCount2 = fileList2.length;
            var cancelScript2 = (inputCount2 === 0);
            if (cancelScript2 === true) {
                alert('No input files found in the 2nd folder, script cancelled!');
                return;
            }
            var inputCount3 = fileList3.length;
            var cancelScript3 = (inputCount3 === 0);
            if (cancelScript3 === true) {
                alert('No input files found in the 3rd folder, script cancelled!');
                return;
            }

            // Validate that the input folders have matching file list quantities
            if (inputCount2 !== inputCount1 || inputCount3 !== inputCount2) {
                alert('The input folders do not contain the same quantities of files, script cancelled!');
                return;
            }

            // Set the output folder
            var outputFolder = inputFolder1.parent + "/";

            // or

            /*
            // Select the output folder
            var outputFolder = Folder.selectDialog("Please select the output folder:");
            if (outputFolder === null) {
                return;
            }
            */

            // Set the file processing counter
            var fileCounter = 0;

            // Open the files
            while (fileList1.length) {
                for (var a = 0; a < 1; a++) {
                    try {
                        app.open(fileList1.pop());
                        app.open(fileList2.pop());
                        if (app.documents[1].name != app.documents[0].name) {
                            alert('Name mismatch in the 2nd folder, script cancelled!');
                            return;
                        }
                        app.open(fileList3.pop());
                        if (app.documents[2].name != app.documents[0].name) {
                            alert('Name mismatch in the 3rd folder, script cancelled!');
                            return;
                        }
                    } catch (e) {}
                }

                // 1st doc
                app.activeDocument = documents[0];
                docNameToLayerName();
                activeDocument.activeLayer.name = inputFolder1.name + " - " + activeDocument.activeLayer.name;

                // Stack the 2nd and 3rd docs
                while (app.documents.length > 1) {
                    // 2nd doc
                    app.activeDocument = documents[1];
                    docNameToLayerName();
                    activeDocument.activeLayer.name = inputFolder2.name + " - " + activeDocument.activeLayer.name;
                    app.activeDocument.activeLayer.duplicate(documents[0]);
                    app.activeDocument = documents[0];
                    app.documents[1].close(SaveOptions.DONOTSAVECHANGES);
                    // 3rd doc
                    app.activeDocument = documents[1];
                    docNameToLayerName();
                    activeDocument.activeLayer.name = inputFolder3.name + " - " + activeDocument.activeLayer.name;
                    app.activeDocument.activeLayer.duplicate(documents[0]);
                    app.activeDocument = documents[0];
                    app.documents[1].close(SaveOptions.DONOTSAVECHANGES);
                }

                // Run the specified action on the stacked layers
                app.doAction(actionName, actionSet);

                // Save name & save path
                var docName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
                var saveFile = File(outputFolder + '/' + docName + '.psd');

                // Call the save function
                savePSD(saveFile);

                // Close all open files without saving
                while (app.documents.length) {
                    app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                }

                // Increment the file saving counter
                fileCounter++;


                ///// Functions /////

                function savePSD(saveFile) {
                    psdSaveOptions = new PhotoshopSaveOptions();
                    psdSaveOptions.embedColorProfile = true;
                    psdSaveOptions.alphaChannels = true;
                    psdSaveOptions.layers = true;
                    psdSaveOptions.annotations = true;
                    psdSaveOptions.spotColors = true;
                    app.activeDocument.saveAs(saveFile, psdSaveOptions, true, Extension.LOWERCASE);
                }

                function docNameToLayerName() {
                    var layerName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
                    app.activeDocument.activeLayer.name = layerName;
                }
            }

            // Restore saved dialogs
            app.displayDialogs = restoreDialogMode;

            // End of script notification
            app.beep();
            alert('Script completed!' + '\n' + fileCounter + ' combined files saved to:' + '\n' + outputFolder);

            // Open the output folder in the Finder or Explorer
            // outputFolder.execute();

        }());

    } catch (e) {
        // Restore saved dialogs
        app.displayDialogs = restoreDialogMode;
        alert("If you see this message, something went wrong!" + "\r" + e + ' ' + e.line);

    }
} else {
    alert('Please close all open documents before running this script!');
}

 

Stephen Marsh
Community Expert
Stephen MarshCommunity ExpertCorrect answer
Community Expert
March 29, 2023

@djghost1133 

 

I quickly modified an older script from 2 to 3 input folders... I would do things slightly differently today, however, I don't have time at the moment. I'll look at refining the code later based on your feedback.

 

All it does is stack alphabetically sorting files from 3 input folders as a layered PSD. There is no error checking, it is presumed that all three input folders have the same number of files and that they are all named the same.

 

EDIT: Code updated to version 1.1:

 

/*
https://community.adobe.com/t5/photoshop-ecosystem-discussions/need-help-to-create-script-that-stacks-files-with-the-same-names-together/m-p/13688339
v1.1 - 30th March 2023, Stephen Marsh
Based on:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/auto-merge-files/m-p/10753387
*/

#target photoshop

var folder1 = Folder.selectDialog("Please select the 1st input folder");  // input folder 1
var folder2 = Folder.selectDialog("Please select the 2nd input folder");  // input folder 2 
var folder3 = Folder.selectDialog("Please select the 3rd input folder");  // input folder 3 

var saveFolder = Folder.selectDialog("Please select the folder to save to...");  // output folder
var searchMask = '*.???';
var list1 = folder1.getFiles(searchMask);
var list2 = folder2.getFiles(searchMask);
var list3 = folder3.getFiles(searchMask);
list1.sort(); // Alpha-numeric sort
list2.sort(); // Alpha-numeric sort
list3.sort(); // Alpha-numeric sort

app.displayDialogs = DialogModes.NO;

var psdOptions = new PhotoshopSaveOptions();
psdOptions.embedColorProfile = true;
psdOptions.alphaChannels = true;
psdOptions.layers = true;
psdOptions.spotColors = true;

for (var i = 0; i < list1.length; i++) {
    var doc = open(list1[i]);
    var docName = doc.name;
    activeDocument.activeLayer.name = folder1.name + " - " + docName.split('.')[0];
    placeFile(list2[i], 100);
    activeDocument.activeLayer.rasterize(RasterizeType.ENTIRELAYER);
    activeDocument.activeLayer.name = folder2.name + " - " + activeDocument.activeLayer.name;
    placeFile(list3[i], 100);
    activeDocument.activeLayer.rasterize(RasterizeType.ENTIRELAYER);
    activeDocument.activeLayer.name = folder3.name + " - " + activeDocument.activeLayer.name;
    doc.saveAs(new File(saveFolder + '/' + docName.split('.')[0] + '.psd'), psdOptions);
    doc.close(SaveOptions.DONOTSAVECHANGES);
};

alert('Script completed!' + '\n' + 'Files saved to:' + '\r' + saveFolder.fsName);

function placeFile(file, scale) {
    try {
        var idPlc = charIDToTypeID("Plc ");
        var desc2 = new ActionDescriptor();
        var idnull = charIDToTypeID("null");
        desc2.putPath(idnull, new File(file));
        var idFTcs = charIDToTypeID("FTcs");
        var idQCSt = charIDToTypeID("QCSt");
        var idQcsa = charIDToTypeID("Qcsa");
        desc2.putEnumerated(idFTcs, idQCSt, idQcsa);
        var idOfst = charIDToTypeID("Ofst");
        var desc3 = new ActionDescriptor();
        var idHrzn = charIDToTypeID("Hrzn");
        var idPxl = charIDToTypeID("#Pxl");
        desc3.putUnitDouble(idHrzn, idPxl, 0.000000);
        var idVrtc = charIDToTypeID("Vrtc");
        var idPxl = charIDToTypeID("#Pxl");
        desc3.putUnitDouble(idVrtc, idPxl, 0.000000);
        var idOfst = charIDToTypeID("Ofst");
        desc2.putObject(idOfst, idOfst, desc3);
        var idWdth = charIDToTypeID("Wdth");
        var idPrc = charIDToTypeID("#Prc");
        desc2.putUnitDouble(idWdth, idPrc, scale);
        var idHght = charIDToTypeID("Hght");
        var idPrc = charIDToTypeID("#Prc");
        desc2.putUnitDouble(idHght, idPrc, scale);
        var idAntA = charIDToTypeID("AntA");
        desc2.putBoolean(idAntA, true);
        executeAction(idPlc, desc2, DialogModes.NO);

    }
    catch (e) { }
}//end function placeFile

 

  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)

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

 

Participant
March 29, 2023

@Stephen Marsh 

This does exactly what I need. You just saved me a bunch of hours of work. Thanks a ton! 

Participant
March 29, 2023

The script could play the action removing the need for a second pass batch on the stacked PSD files.

 

The save location could be defaulted to the parent folder of the input folders, rather than prompting for the location.

 

The layer names could include their respective input folder names to help identify their source as all three layers have the same name (stacking order from bottom to top does provide a clue).


@Stephen Marsh - I really like the idea of the layers including the source folder, I can see that being helpful. My current action renames layers starting from the top but if they're already named properly that would be awesome. 

 

Having the script play the action likely wouldn't work in my case because I occasionally use different actions for certain products + whatever final specs the client wants although I can likely just change the action in .jsx file and that would still save me a bunch of time.