• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
2

Photoshop javascript: Open files in all subfolders

Explorer ,
Jul 02, 2013 Jul 02, 2013

Copy link to clipboard

Copied

Hi guys

I'm very new to javascript, and general Photoshop scripting. My script is coming on well, but I struggle working with files and folders. It's a lack of basic javascript knowledge, which I need to work on. Right now, I'm trying to expand the image open part of my script, so that it opens images regardless of whether they are in a subfolder or not.

You can see my input folder (C:/Input). I want to be able to throw files in there, some in folders, some not. Out of interest, my outputs will be combined into one output folder... that bit is fine.

var inFolder = new Folder("C:/Input")

if(inFolder != null){

var fileList = inFolder.getFiles(/\.(jpg|tif|psd|bmp|gif|png|)$/i);

}

for(var a = 0 ;a < fileList.length; a++)

{

var docRef = open(fileList);

//do things here

}

Is there an easy way of expanding this to include files in subfolders? All advice greatly appreciated.

Thanks

David

TOPICS
Actions and scripting

Views

34.6K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Guru , Jul 03, 2013 Jul 03, 2013

You could combine the code you posted with the code I posted like this:

var topFolder = new Folder('~/desktop/test');
var fileandfolderAr = scanSubFolders(topFolder,/\.(jpg|tif|psd|bmp|gif|png|)$/i);

var fileList = fileandfolderAr[0];

for(var a = 0 ;a < fileList.length; a++)

{

var docRef = open(fileList);

//do things here

}

function scanSubFolders(tFolder, mask) { // folder object, RegExp or string
    var sFolders = new Array();
    var allFiles = new Array();
    sFolders[0] = tFolder;
    for (var j

...

Votes

Translate

Translate
Adobe
Guru ,
Jul 02, 2013 Jul 02, 2013

Copy link to clipboard

Copied

Folder.getFiles() only works with one folder at a time. To get all the files in the folder as well as in subfolders you need to scan each subfolder. One way to do that is with a recursive function. Something like this:

var topFolder = new Folder('~/desktop/test');

var fileandfolderAr = scanSubFolders(topFolder,/\.(jpg|tif|psd|bmp|gif|png|)$/i);

alert('Scan of ' + topFolder.fullName + '\n' + fileandfolderAr[0].length + ' files\nLast File: ' + decodeURI(fileandfolderAr[0][fileandfolderAr[0].length-1]));

alert('Scan of ' + topFolder.fullName + '\n' + fileandfolderAr[1].length + ' folders\nLast Folder: ' + decodeURI(fileandfolderAr[1][fileandfolderAr[1].length-1]));

function scanSubFolders(tFolder, mask) { // folder object, RegExp or string

    var sFolders = new Array();

    var allFiles = new Array();

    sFolders[0] = tFolder;

    for (var j = 0; j < sFolders.length; j++){ // loop through folders            

        var procFiles = sFolders.getFiles();

        for (var i=0;i<procFiles.length;i++){ // loop through this folder contents

            if (procFiles instanceof File ){

                if(mask==undefined) allFiles.push(procFiles);// if no search mask collect all files

                if (procFiles.fullName.search(mask) != -1) allFiles.push(procFiles); // otherwise only those that match mask

        }else if (procFiles instanceof Folder){

            sFolders.push(procFiles);// store the subfolder

            scanSubFolders(procFiles, mask);// search the subfolder

         }

      }

   }

   return [allFiles,sFolders];

};

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Sep 11, 2020 Sep 11, 2020

Copy link to clipboard

Copied

this is an excellent answer but you forgot to put the index numbers in in Files within the loop... it should look like in the code below.

 

 

function traverseFolder(path) {

// Create new folder object based on path string
var folder = new Folder(path);

// Get all files in the current folder
var files = folder.getFiles();

// Loop over the files in the files object
for (var i = 0; i < files.length; i++) {

// Check if the file is an instance of a file
// else call the traverse folder recursively with the current folder as an argument

if (files[i] instanceof File) {

// Convert the file object to a string for matching purposes (match only works on String objects)
var fileString = String(files[i]);
// Check if the file contains the right extension

if (fileString.match(/.(html)$/)) {

// Do something if the file matches
$.writeln(fileString + ' : This is a html file' + "\n");

} else {

// Do something if the file doesn't match
$.writeln(fileString + ' : This is NOT an html file' + "\n");

}

} else {
$.writeln('passing folder: ' + files[i] + "\n");

// Call method recursively with the current folder as an argument
traverseFolder(files[i]);
}

}

}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Jul 02, 2013 Jul 02, 2013

Copy link to clipboard

Copied

var traverseFolder = function(path)

{

     // Create new folder object based on path string

     var folder = new Folder(path);

     // Get all files in the current folder

     var files = folder.getFiles();

     // Loop over the files in the files object

     for (var i = 0; i &lt; files.length; i++)

     {

          // Check if the file is an instance of a file

          // else call the traverse folder recursively with the current folder as an argument

          if (files instanceof File)

          {

               // Convert the file object to a string for matching purposes (match only works on String objects)

               var fileString = String(files);

               // Check if the file contains the right extension

               if (fileString.match(/.(jpg|tif|psd|bmp|gif|png)$/))

               {

                    // Do something if the file matches

                    alert(fileString + 'good file');

               }

               else

               {

                    // Do something if the file doesn't match

                    alert(fileString + 'bad file');

               }

          }

          else

          {

               alert('passing folder: ' + files);

               // Call method recursively with the current folder as an argument

               traverseFolder(files);

          }

     }

}

traverseFolder('c:/path');

You can use the traverseFolder() function and pass the path as a parameter. Make sure to delete the alerts, there just there to show you which folder/file is currently being loaded. Also make sure to delete the comments in the for statement, since they cause the program to slow down unneccesarily.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guru ,
Jul 02, 2013 Jul 02, 2013

Copy link to clipboard

Copied

Pascalculator wrote:

... make sure to delete the comments in the for statement, since they cause the program to slow down unneccesarily.

The comments will not effect the speed of the script as it runs. If the comments help you remember what the script does, how it does what it does, or how to use it I suggest leaving them in.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jul 03, 2013 Jul 03, 2013

Copy link to clipboard

Copied

Thank you Michael and Pascalculator for your explanations, I'm very grateful. I've struggled a little to integrate either into my script - I will close myself in a dark room later and work on it. I'll get back when I've figured it!

Thanks

David

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guru ,
Jul 03, 2013 Jul 03, 2013

Copy link to clipboard

Copied

You could combine the code you posted with the code I posted like this:

var topFolder = new Folder('~/desktop/test');
var fileandfolderAr = scanSubFolders(topFolder,/\.(jpg|tif|psd|bmp|gif|png|)$/i);

var fileList = fileandfolderAr[0];

for(var a = 0 ;a < fileList.length; a++)

{

var docRef = open(fileList);

//do things here

}

function scanSubFolders(tFolder, mask) { // folder object, RegExp or string
    var sFolders = new Array();
    var allFiles = new Array();
    sFolders[0] = tFolder;
    for (var j = 0; j < sFolders.length; j++){ // loop through folders            
        var procFiles = sFolders.getFiles();
        for (var i=0;i<procFiles.length;i++){ // loop through this folder contents
            if (procFiles instanceof File ){
                if(mask==undefined) allFiles.push(procFiles);// if no search mask collect all files
                if (procFiles.fullName.search(mask) != -1) allFiles.push(procFiles); // otherwise only those that match mask
        }else if (procFiles instanceof Folder){
            sFolders.push(procFiles);// store the subfolder
            scanSubFolders(procFiles, mask);// search the subfolder
         }
      }
   }
   return [allFiles,sFolders];
};

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jul 03, 2013 Jul 03, 2013

Copy link to clipboard

Copied

Thanks so much, Micheal, for all your help. It's working fantastically, I really appreciate all your input, and to Pascalculator. Will try to pay back the community. : )

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Apr 04, 2014 Apr 04, 2014

Copy link to clipboard

Copied

Hello,

Inspired by the topic created a script that converts files .eps to .jpg. However, I have a problem. The script correctly reads the folders and subfolders and contained in their files and saves the converted files to the input folder.

I do not know how to save the converted file ".jpg" to the folder from which it was read source file.

Please suggestions on how to solve this problem.

My script looks like this:

function saveJPEG( doc, saveFile, qty ) {

   var saveOptions = new JPEGSaveOptions( );

   saveOptions.embedColorProfile = true;

   saveOptions.formatOptions = FormatOptions.STANDARDBASELINE;

   saveOptions.matte = MatteType.NONE;

   saveOptions.quality = qty;

   doc.saveAs( saveFile, saveOptions, true );

};

function scanSubFolders(tFolder, mask) { // folder object, RegExp or string

    var sFolders = new Array();

    var allFiles = new Array();

    sFolders[0] = tFolder;

    for (var j = 0; j < sFolders.length; j++){ // loop through folders           

        var procFiles = sFolders.getFiles();

        for (var i=0;i<procFiles.length;i++){ // loop through this folder contents

            if (procFiles instanceof File ){

                if(mask==undefined) allFiles.push(procFiles);// if no search mask collect all files

                if (procFiles.fullName.search(mask) != -1) allFiles.push(procFiles); // otherwise only those that match mask

        }else if (procFiles instanceof Folder){

            sFolders.push(procFiles);// store the subfolder

            scanSubFolders(procFiles, mask);// search the subfolder

         }

      }

   }

   return [allFiles,sFolders];

};

function fitImage( xUnitValue, yUnitValue ){

var fitImage = stringIDToTypeID( "3caa3434-cb67-11d1-bc43-0060b0a13dc4" );

    var size = new ActionDescriptor();

    size.putUnitDouble( charIDToTypeID( "Wdth" ), charIDToTypeID( "#Pxl" ), xUnitValue.as( 'px' ) );

    size.putUnitDouble( charIDToTypeID( "Hght" ), charIDToTypeID( "#Pxl" ), yUnitValue.as( 'px' ) );

executeAction( fitImage, size, DialogModes.NO );

};

var openOptions = new EPSOpenOptions();

openOptions.antiAlias = true;

openOptions.constrainProportions = true;

openOptions.mode = OpenDocumentMode.RGB;

openOptions.resolution = 600

var x = new UnitValue( 1280, 'px' );

var y = new UnitValue( 1024, 'px' );

var inputFolder = Folder.selectDialog (prompt);

var outputFolder = inputFolder;

var fileandfolderAr = scanSubFolders(inputFolder,/\.(eps|)$/i);

var fileList = fileandfolderAr[0];

for(  var i =0; i < fileList.length; i++ ) {

   var doc = open( fileList[ i ], openOptions );      var docName = decodeURI ( doc.name );

   docName = docName.match( /(.*)(\.[^\.]+)/ ) ? docName = docName.match( /(.*)(\.[^\.]+)/ ) : docName = [ docName, docName, undefined ];

   var saveName = docName[ 0 ]; // strip the extension

   var saveFile =  new File ( outputFolder + '/' + saveName + '.jpg' );

       doc.resizeImage( undefined, undefined, 72, ResampleMethod.NONE );

   doc.flatten( );

   doc.convertProfile( 'sRGB IEC61966-2.1', Intent.RELATIVECOLORIMETRIC, true, true );

   fitImage( x, y );

   saveJPEG( doc, saveFile, 8 );// or

   //exportSFW( doc, saveFile, 65 );

   doc.close( SaveOptions.DONOTSAVECHANGES );

}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jul 31, 2016 Jul 31, 2016

Copy link to clipboard

Copied

In the last part of code in linecode:

var saveFile =  new File ( outputFolder + '/' + saveName + '.jpg' );

replace outputFolder with activeDocument.path, so you'll get:

var saveFile =  new File ( activeDocument.path + '/' + saveName + '.jpg' );

I hope it will work, because I had to do two other little changes:

  • I deleted EPS options from var doc = open( fileList[ i ], openOptions ); as I had no EPS files and were opening JPG's
  • in fitImage function I had to change in 2 following lines xUnitValue.as('px') for xUnitValue and yUnitValue.as('px') for yxUnitValue (maybe because I tested it in CS2 that second change was necessary)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 31, 2016 Jul 31, 2016

Copy link to clipboard

Copied

Kukurykus wrote:

replace outputFolder with activeDocument.path, so you'll get:

  1. varsaveFile=newFile(activeDocument.path+'/'+saveName+'.jpg');

That will only work for old documents when the  Active document has been save in the past then there is a backing file and path.  It will not work for new Photoshop documents there is no activeDocument.path or backing file.

JJMack

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jul 31, 2016 Jul 31, 2016

Copy link to clipboard

Copied

That's true, but there is backing file so the path as there are EpsOpenOptions and  Folder.selectDialog (prompt)  in the code. But that had to be a tip just in case I guess 🙂

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Sep 28, 2019 Sep 28, 2019

Copy link to clipboard

Copied

Error 4: sFolders.getFiles is not a function.

Line 21

var procFiles = sFolders.getFiles();

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Dec 16, 2020 Dec 16, 2020

Copy link to clipboard

Copied

GO to xbytor tools-ActionEvalDemo script-line 8873

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Dec 28, 2020 Dec 28, 2020

Copy link to clipboard

Copied

For some reason the "traverseFolder" function from above has a problem, when one or more matching files are located in the source folder (and not in a subfolder). Therefore I focused on the "scanSubFolders" function from @Michael_L_Hale and had the same issue like you @sanjayam47827904. I'm a javascript beginner and so I tried to adjust this code in order to make it work out. Finally this is my solution - basically the index variables of the different arrays have been missing. So I added them and it seems to work out properly.

var topFolder = new Folder('~/Desktop/PS_TEST');
var fileandfolderAr = scanSubFolders(topFolder, /\.(jpg|tif|psd|bmp|gif|png|)$/i);
var fileList = fileandfolderAr[0];

//all file paths found and amount of files found
alert("fileList: " + fileList + "\n\nFile Amount: " + fileList.length);

for(var a = 0 ; a < fileList.length; a++) {
var docRef = open(fileList[a]);
//do things here
}

function scanSubFolders(tFolder, mask) { // folder object, RegExp or string
    var sFolders = [];
    var allFiles = [];
    sFolders[0] = tFolder;
    for (var j = 0; j < sFolders.length; j++) { // loop through folders
        var procFiles = sFolders[j].getFiles();
        for (var i = 0; i < procFiles.length; i++) { // loop through this folder contents
            if (procFiles[i] instanceof File ) {
                if(mask == undefined) {
                    allFiles.push(procFiles); // if no search mask collect all files
                }
                if (procFiles[i].fullName.search(mask) != -1) {
                    allFiles.push(procFiles[i]); // otherwise only those that match mask
                }
            }
            else if (procFiles[i] instanceof Folder) {
                sFolders.push(procFiles[i]); // store the subfolder
                scanSubFolders(procFiles[i], mask); // search the subfolder
            }
        }
    }
    return [allFiles,sFolders];
}

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Jan 19, 2021 Jan 19, 2021

Copy link to clipboard

Copied

Thanks for correcting this error, this script will help me a lot.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jan 20, 2021 Jan 20, 2021

Copy link to clipboard

Copied

I have the situation where 'instanceof File' returns 'false' for all files and folders.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Aug 03, 2022 Aug 03, 2022

Copy link to clipboard

Copied

Thank you for fixing it.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 03, 2022 Aug 03, 2022

Copy link to clipboard

Copied

LATEST

Thanks, the change in forum software broke many old scripts []

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines