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
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
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];
};
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.
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 < 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.
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.
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
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
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];
};
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. : )
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 );
}
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:
Copy link to clipboard
Copied
Kukurykus wrote:
var saveFile = new File ( outputFolder + '/' + saveName + '.jpg' );
replace outputFolder with activeDocument.path, so you'll get:
var saveFile = new File ( 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.
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 🙂
Copy link to clipboard
Copied
Error 4: sFolders.getFiles is not a function.
Line 21
var procFiles = sFolders.getFiles();
Copy link to clipboard
Copied
GO to xbytor tools-ActionEvalDemo script-line 8873
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];
}
Copy link to clipboard
Copied
Thanks for correcting this error, this script will help me a lot.
Copy link to clipboard
Copied
I have the situation where 'instanceof File' returns 'false' for all files and folders.
Copy link to clipboard
Copied
Thank you for fixing it.
Copy link to clipboard
Copied
Thanks, the change in forum software broke many old scripts []