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

Make subfolder script work on CS5..

Participant ,
Apr 08, 2019 Apr 08, 2019

Hi,

I'm working in a company where allot of people are still working on CS5.

I'm also working on a few new automation scripts that use a script to search in subfolders.

It's a recursive script that every time when it finds a subfolder, it runs the function on that folder again.

And adds all files found to an array.

Everything works perfect on CC 2018, but it doesn't on CS5.

It only finds the files in the root folder, the recursive part doesn't seem to work, and I don't know why.

It doesn't show an error, it just doesn't scan the subfolders.

I found this code on the forum that I use...

I think I understand the way it works, but why it doesnt work on SC5, no idea...

Upgrading all licences to CC2018 is costly, Most licences are only used for exporting document with scripts.

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

Moderator: Moved from Adobe Creative Cloud​ to Photoshop Scripting

TOPICS
Actions and scripting
1.1K
Translate
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
Adobe
Community Expert ,
Apr 08, 2019 Apr 08, 2019

Discussion successfully moved from Forum comments to Adobe Creative Cloud.​

If a different moderator finds out the best scripting forum, he can move the thread there. "Forum Comments" should be used for reporting and discussing forum problems.

ABAMBO | Hard- and Software Engineer | Photographer
Translate
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 ,
Apr 09, 2019 Apr 09, 2019

Moving to  Photoshop Scripting

My System: Intel i7-8700K - 64GB RAM - NVidia Geforce RTX 3060 - Windows 11 Pro 24H2 -- LR-Classic 14 - Photoshop 26 - Nik Collection 7 - PureRAW 4 - Topaz PhotoAI 3
Translate
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 ,
Apr 08, 2019 Apr 08, 2019

from where does this script is executed, which software ?

Translate
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
Guide ,
Apr 08, 2019 Apr 08, 2019

That is badly written, you are overwriting sFolders and allFiles each time you are calling the scanSubFolders function. It just will not work!

You could do something on the lines of:-

#target photoshop;

app.bringToFront();

var folders =[];

var topLevel = Folder.selectDialog("Please select top level folder");   

folders = FindAllFolders(topLevel, folders);

folders.unshift(topLevel);

//you now have an array of all sub folders

//Process folders

for(var f in folders){

//get an array of files

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

//process files in fileList

for(var jp in fileList){

    app.open(fileList[jp]);

    //do what ever you want

    //do your save

    //close document.

    app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);

    }//end fileList

}//end folders

//Function to get all sub folders.

function FindAllFolders( srcFolderStr, destArray) {

var fileFolderArray = Folder( srcFolderStr ).getFiles();

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

var fileFoldObj = fileFolderArray;

if ( fileFoldObj instanceof File ) {} else {

destArray.push( Folder(fileFoldObj) );

FindAllFolders( fileFoldObj.toString(), destArray );

        }

    }

    return destArray;

};

Translate
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
Participant ,
Apr 08, 2019 Apr 08, 2019

Thanks for all the help!

I have not tried your script yet, I first tried to figure out whats going on with my script, but I will give it a try!

I'm using Photoshop CC2018, and my scripts also needs to run on Photoshop CS5.

I made a function based on the subfolder function I found here...

Photoshop javascript: Open files in all subfolders

This function gives me unreliable results.

Yesterday I discovered that is has all to do with the mask.

The function I created works as follows..

input the folder, if it needs to scan the subfolders, true or false, and the match mask.

It only works in a few cases, and CC2018 is responding different from CS5.

Here are my results on a test folder with a total of 5 files and 3 subfolders, 1 file in the root, 3 in the subfolder, and 1 more in a subfolder inside the subfolder.

The scrips report....

cc2018+ "/\.(jpg|psd|bmp|gif|png|)$/i" mask - correct!... 5 files, 2 folders

cc2018+ "[]" mask - correct!... 5 files, 2 folders

cc2018+ "undefined" mask - fail... 10 files, 2 folders

cs5+ "/\.(jpg|psd|bmp|gif|png|)$/i" mask - fail... 1 file, 2 folders

cs5+ "[]" mask - correct!... 5 files, 2 folders

cs5+ "undefined" mask - fail... 10 files, 2 folders

So it seems, when the mask is undefined, it counts the files double.

When the mask is "[]" it works correct, both on CC2018 and CS5.

When the mask is "/\.(jpg|psd|bmp|gif|png|)$/i", it works correctly on CC2018, but on CS5, only on the root folder, and not on the recursive functions.

I can add to the function "if(mask == undefined){var mask = [];}"

that way the undefined runs are working on CC2018 and CS5, but when I search for jpg files, that mask still only works on CC2018, maybe I can reformulate the mask search?

I also let it report back the number of files and folders found.

That works easy for me, because photoshop seems to fail to alert array.lenght for some reason.

My current script can also be improved so it won't report the rootfolder back, as it does now, it includes the folder you input in the function.

The counters does not count the root, so thats easy to work with, and it can report in an alert.

My current function testing script...

// Function: Scan folder, with or without subfolders, and counts files and folders

function scanFolder(theFolder, subFolder, mask){

    var theFolder = new Folder (theFolder);

    var sFolders = new Array();

    var allFiles = new Array();

    var fileCount = 0;

    var folderCount = 0;

    var runOnce = false;

    sFolders[0] = theFolder;

   

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

       

        if (subFolder == false)  {

            runOnce = true;

            }

        var procFiles = sFolders.getFiles();

       

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

           

            if (procFiles instanceof File )  {

                if(mask==undefined) {

                    allFiles.push(procFiles);

                    var fileCount = fileCount + 1;

                    }

                if (procFiles.fullName.search(mask) != -1)   {

                    allFiles.push(procFiles);

                    var fileCount = fileCount + 1;

                    }

        }else if (procFiles instanceof Folder)   {

            sFolders.push(procFiles);

            var folderCount = folderCount + 1;

         }

      }

   }

   return [allFiles,sFolders,fileCount,folderCount]

}

var theFolder = Folder.selectDialog ("Select folder");

var filesandfolders = scanFolder(theFolder,true,/\.(jpg|psd|bmp|gif|png|)$/i);

var allFiles = filesandfolders[0];

var sFolders = filesandfolders[1];

var fileCount = filesandfolders[2];

var folderCount = filesandfolders[3];

alert("fileCount: " + fileCount + "\nfolderCount: " + folderCount + "\n\nallFiles: \n" + allFiles.join('\n') + "\n\nsFolders: \n" + sFolders.join('\n'));

Translate
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
Guide ,
Apr 09, 2019 Apr 09, 2019

You are not using recursion in your function so it will only find files/folders in the top level folder. The recursive function that you were originally using was resetting the arrays each time it called itself, so only the last folder details would have been returned.

You will see in my recursive function it is passing the array back to itself.

Translate
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
Participant ,
Apr 09, 2019 Apr 09, 2019

Thanks for your script.

I'm a beginner in javascript, and I'm having dificulties modifying your script to put it all in a working function.

Your script is not entirely inside a function.

I need a function that I give the folder to scan, a true/false for only scanning the root folder, or all infinite subfolder depth, and including a filter mask. The function should output an array of all the files found in all folders of finite folder depth, and an array of all folders of finite folder depth, or only the root when subFolder = false.

And the number of files and folders found.

Is it possible to change my function (as little as possible) to make it correctly recursive, feeding back the array?

The strange thing is, my function does works, depending on the mask used.. Is the mask related to the recursive array thing?

function scanFolder(theFolder, subFolder, mask){

xxxxxx

   return [allFiles,sFolders,fileCount,folderCount]

}

Translate
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
Participant ,
Apr 09, 2019 Apr 09, 2019

I surprised myself!

I was able to modify your script to make it work the way I want...

But.. There still is an issue going on with CS5... maybe because my modifications, because it all has to do with the mask.. still

When I run the code below

On CS5, with the mask "/\.(tif|jpg|psd|bmp|gif|png|)$/i" it only finds the file in the root. With mask "[]" or undefined, it works correctly!

And on CC2018, it works on all masks!

But Why is the "/\.(tif|jpg|psd|bmp|gif|png|)$/i" not working recursively?

This code is your code that I modified...

//Function to get all sub folders. 

function findAllFilesAndFolders( srcFolderStr, fileArray, folderArray, subFolder, mask) { 

    var fileFolderArray = Folder( srcFolderStr ).getFiles(); 

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

    var fileFoldObj = fileFolderArray

    if ( fileFoldObj instanceof File ) {

        if (fileFoldObj.fullName.search(mask) != -1) {

            fileArray.push( Folder(fileFoldObj) );

            }

        } else { 

            folderArray.push( Folder(fileFoldObj) );

            if(subFolder == true){

                findAllFilesAndFolders( fileFoldObj.toString(), fileArray, folderArray, subFolder, mask);

                }

            } 

        } 

    return [fileArray, folderArray]; 

}; 

var fileArray =[];

var folderArray =[];

var topLevel = Folder.selectDialog ("Select folder");

filesAndFoldersArray = findAllFilesAndFolders(topLevel, fileArray, folderArray, true, /\.(tif|jpg|psd|bmp|gif|png|)$/i);

alert("fileArray: \n" + fileArray.join('\n') + "\n\nsfolderArray: \n" + folderArray.join('\n'));

Translate
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
Guide ,
Apr 09, 2019 Apr 09, 2019

Please try this...

var mask = new RegExp(/\.(jpg|psd|bmp|gif|png|)$/i);

var topLevel = Folder.selectDialog("Please select top level folder");  

var folderFiles={};

folderFiles.files=[];

folderFiles.folders=[];

folderFiles = FindAllFolders( topLevel, folderFiles,mask);

$.writeln("Number of folders = " + folderFiles.folders.length);

$.writeln("Number of Files = " + folderFiles.files.length);

for(var a in folderFiles.folders){ $.writeln(a + " = " + decodeURI(folderFiles.folders));}

for(var a in folderFiles.files){ $.writeln(a + " = " + decodeURI(folderFiles.files));}

function FindAllFolders( srcFolderStr, destArray,mask) { 

var fileFolderArray = Folder( srcFolderStr ).getFiles(); 

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

var fileFoldObj = fileFolderArray

if ( fileFoldObj instanceof File ) {

    if(fileFoldObj.toString().match(mask)) destArray.files.push( File(fileFoldObj) );

    } else { 

destArray.folders.push( Folder(fileFoldObj) ); 

FindAllFolders( fileFoldObj.toString(), destArray ,mask); 

        } 

    } 

    return destArray; 

}; 

Translate
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
Participant ,
Apr 09, 2019 Apr 09, 2019

Thanks!

Running your code on CS5 works, it reports the correct files, and applying the mask on the search.

I only had to changed all the $.writeln to alert.

I worked on your code that I modified, and checked it the mask variable was inputted to the recursive functions, by checking with alert every time the function runs,and it shows up correctly.

But when I change the "findAllFilesAndFolders( fileFoldObj.toString(), fileArray, folderArray, subFolder, mask);" and changed mask to /\.(jpg|psd|bmp|gif|png|)$/i, it did work perfectly recursively on CS5, but than I can't change the mask parameter by calling the function. No idea where it goes wrong.

Your last code works, but harder to understand for me.

Can you make a change to this code, maybe now you know where the problem lies?

I have put the function in another function so it's not putting it in a global array, so I can save seperate array's from this function, not sure if this is the way tot do it, maybe you see something bad here. But it works, apart from the mask issue on CS5...

[CODE]

// Function: Scan folder, with or without subfolders, and counts files and folders

function scanFolder(theFolder, subFolder, mask){

   

    //Function to get all sub folders. 

    function findAllFilesAndFolders( theFolder, fileArray, folderArray, subFolder, mask) { 

        //alert("mask constructor name: " + mask.constructor.name + "mask: " + mask);

        var fileFolderArray = Folder( theFolder ).getFiles(); 

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

        var fileFoldObj = fileFolderArray

        if ( fileFoldObj instanceof File ) {

            if (fileFoldObj.fullName.search(mask) != -1) {

                fileArray.push( Folder(fileFoldObj) );

                }

            } else { 

                folderArray.push( Folder(fileFoldObj) );

                if(subFolder == true){

                    findAllFilesAndFolders( fileFoldObj.toString(), fileArray, folderArray, subFolder, mask);

                    }

                } 

            } 

        return [fileArray, folderArray]; 

    }; 

   

    var fileArray =[];

    var folderArray =[];

    var filesAndFoldersArray = findAllFilesAndFolders(theFolder, fileArray, folderArray, subFolder, mask);

   return [fileArray,folderArray]

}

var theFolder = Folder.selectDialog ("Select folder");

filesAndFoldersArray = scanFolder(theFolder, true, /\.(tif|jpg|psd|bmp|gif|png|)$/i);

var fileArray = filesAndFoldersArray[0]

var folderArray = filesAndFoldersArray[1]

alert("fileArray: \n" + fileArray.join('\n') + "\n\nsfolderArray: \n" + folderArray.join('\n'));

[/CODE]

Translate
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
Guide ,
Apr 09, 2019 Apr 09, 2019

You could simplify it by using a couple of Global Variables:-

var mask = new RegExp(/\.(jpg|psd|bmp|gif|png|)$/i);

var theFolder = Folder.selectDialog("Please select top level folder"); 

fileArray = new Array();

folderArray = new Array();

var fileDetails = findAllFilesAndFolders( theFolder, mask) ;

alert("Number of files = " +fileArray.length + "\n" + "Number of folders = " + folderArray.length);

 

    function findAllFilesAndFolders( theFolder, mask) { 

        var fileFolderArray = Folder( theFolder ).getFiles(); 

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

        var fileFoldObj = fileFolderArray

        if ( fileFoldObj instanceof File ) {

            if (fileFoldObj.fullName.search(mask) != -1) {

                fileArray.push( File(fileFoldObj) );

                }

            } else { 

                folderArray.push( Folder(fileFoldObj) );

                    findAllFilesAndFolders( fileFoldObj.toString(),  mask);

                } 

            } 

    }; 

Translate
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
Participant ,
Apr 09, 2019 Apr 09, 2019

I modified your code to fit in a function I can use in my scripts..

It works as far as I can see in all situations, also in CS5.

I would really like to know why the new code works..?!

This is the code that works!...

function scanFolder(srcFolderStr, subFolder, mask){

    function FindAllFolders( srcFolderStr, destArray, mask) {   

        var fileFolderArray = Folder( srcFolderStr ).getFiles();   

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

            var fileFoldObj = fileFolderArray;   

                if ( fileFoldObj instanceof File ) { 

                    if(fileFoldObj.toString().match(mask)) destArray.files.push( File(fileFoldObj) ); 

                        } else {   

                            destArray.folders.push( Folder(fileFoldObj) );

                            if(subFolder == true){

                                FindAllFolders( fileFoldObj.toString(), destArray ,mask);

                                }

                            }   

                        }   

                    return destArray;   

                };

   

    var folderFiles={}; 

    folderFiles.files=[]; 

    folderFiles.folders=[]; 

    folderFiles = FindAllFolders( srcFolderStr, folderFiles,mask); 

   

    return folderFiles;

    }

var theFolder = Folder.selectDialog("Please select top level folder");    

filesAndFoldersArray = scanFolder(theFolder, true, /\.(jpg|psd|bmp|gif|png|)$/i);

alert("fileArray: \n" + filesAndFoldersArray.files.join('\n') + "\n\nsfolderArray: \n" + filesAndFoldersArray.folders.join('\n'));

The code below is the previous code that did not work on CS 5.

function scanFolder(theFolder, subFolder, mask){

   

    function findAllFilesAndFolders( theFolder, fileArray, folderArray, subFolder, mask) { 

       

       

        var fileFolderArray = Folder( theFolder ).getFiles(); 

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

        var fileFoldObj = fileFolderArray

        if ( fileFoldObj instanceof File ) {

            if (fileFoldObj.fullName.search(mask) != -1) {

                fileArray.push( Folder(fileFoldObj) );

                }

            } else { 

                folderArray.push( Folder(fileFoldObj) );

                if(subFolder == true){

                    findAllFilesAndFolders( fileFoldObj.toString(), fileArray, folderArray, subFolder, mask);

                    }

                } 

            } 

        return [fileArray, folderArray]; 

    }; 

   

    var fileArray =[];

    var folderArray =[];

    var filesAndFoldersArray = findAllFilesAndFolders(theFolder, fileArray, folderArray, subFolder, mask);

   return [fileArray,folderArray]

}

var theFolder = Folder.selectDialog ("Select folder");

filesAndFoldersArray = scanFolder(theFolder, true, /\.(jpg|psd|bmp|gif|png|)$/i);

var fileArray = filesAndFoldersArray[0]

var folderArray = filesAndFoldersArray[1]

alert("fileArray: \n" + fileArray.join('\n') + "\n\nsfolderArray: \n" + folderArray.join('\n'));

Translate
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
People's Champ ,
Apr 09, 2019 Apr 09, 2019
LATEST

Very similar to the bug described by Kukurykus here RegExp search bug - PS-SCRIPTS.COM

Just for CS5.

Translate
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