Make subfolder script work on CS5..
Copy link to clipboard
Copied
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
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
Explore related tutorials & articles
Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
Moving to Photoshop Scripting
Copy link to clipboard
Copied
from where does this script is executed, which software ?
Copy link to clipboard
Copied
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;
};
Copy link to clipboard
Copied
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
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'));
Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
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]
}
Copy link to clipboard
Copied
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'));
Copy link to clipboard
Copied
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;
};
Copy link to clipboard
Copied
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]
Copy link to clipboard
Copied
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);
}
}
};
Copy link to clipboard
Copied
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'));
Copy link to clipboard
Copied
Very similar to the bug described by Kukurykus here RegExp search bug - PS-SCRIPTS.COM
Just for CS5.

