Copy link to clipboard
Copied
Hello, I'm running into an issue as I'm not too familiar with the scripting and batch processing side of Photoshop. But here's the dilemma, I have a script that adds a bunch of effects to an image that I'm interested in, and would like to batch process a couple thousand images with this script. Although, the batch process only lets me pick actions. I tried to create an action of the script working, but that didn't work. How do I batch images with a script?
Easy way to include script in action is to place script in Presets > Scripts folder so you can see it in File > Scripts. WHile recording action just select script or even use Insert Menu Item to run script by action.
Copy link to clipboard
Copied
Look at the batch script that are available to you. Adobe Image Processor... and the better web download Plug-in script Image processor Pro... You can include actions in their processing and those actions can use the scripts you have created. So you are batching your scripts. It is also quit easy to create image file list with simple script functions for your scripts to batch process without needing to create a scriptUI dialog for the script. I have created a few functions myself for creating image file list. I have create an example script you can look at here:
/* =======================================================================
// 2021 John J. McAssey (JJMack)
// ======================================================================= */
// This script is supplied as is. It is provided as freeware.
// The author accepts no liability for any problems arising from its use.
// enable double-clicking from Mac Finder or Windows Explorer
#target photoshop // this command only works in Photoshop CS2 and higher
// bring application forward for double-click events
app.bringToFront();
/////////////////////////////////////////////////////////////////////////
// SET-UP Global Variables //
/////////////////////////////////////////////////////////////////////////
var scriptPath = $.fileName.substr(0,$.fileName.lastIndexOf("/")+1);
var scriptName = $.fileName.substr($.fileName.lastIndexOf("/")+1,$.fileName.lastIndexOf("."));
scriptName = scriptName.substr(0,scriptName.lastIndexOf("."));
var scriptExt = $.fileName.substr($.fileName.lastIndexOf("."));
//alert(scriptPath + scriptName + scriptExt);
// Initialize variables used in mainline
var folderListCopy = new Array;
var fileListCopy = new Array;
var fileTypes = "";
var logData = "";
// Save the current preferences and Set Photoshop to use pixels and display no dialogs
var startRulerUnits = app.preferences.rulerUnits;
var startTypeUnits = app.preferences.typeUnits;
var startDisplayDialogs = app.displayDialogs;
app.displayDialogs = DialogModes.NO;
app.preferences.rulerUnits = Units.PIXELS;
app.preferences.typeUnits = TypeUnits.PIXELS;
try {
startDate = (getDateTime());
var time1 = Number(timeString());
var processed = main(); // Select root folder and file types to process, crawl tree creating folderList and fileList then process file list
if (processed!=undefined) { } //alert(processed + " Files Processed");
if (logData!="") logInfo(timeStamp() + "\nFolders " + folderListCopy.length + " Files " + fileListCopy.length + "\n" + fileTypes + "\n\n" + logData);
var time2 = Number(timeString());
endDate = (getDateTime());
alert(startDate + " Start\n"
// +((time2-time1)/1000 )+" Seconds "
+((time2-time1)/60000 ).toPrecision(2)+" Minutes "
// +((time2-time1)/3600000 ).toPrecision(1)+" Hours "
+ "\n" + endDate + " End"
+"\nProcessed " + folderListCopy.length + " Folders Selected " + fileListCopy.length + " Files Types Matching\n"
+ fileTypes + "\n"
);
}
catch(e) { alert(e + ': on line ' + e.line, 'Photoshop Error', true); }
// Return the app preferences
app.preferences.rulerUnits = startRulerUnits;
app.preferences.typeUnits = startTypeUnits;
app.displayDialogs = startDisplayDialogs;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function main() {
//var files = buildFilelist (); // Select image files from any folder till you stop and cancel
//var files = selectFile(true); // Select Image files from a single folder
//var files = selectsImagesFolder("x","x","jpg|jpe"); // Select a folder containg Image tree all jpeg image file types in the tree will be selected
//var files = selectsImagesFolder(true,true,"jpg|jpeg"); // Select the root of the Image tree all jpeg image file types in the tree will be selected
//var files = selectsImagesFolder(true,false); // Select the root of the Image tree all image file types in the tree will be Selected
//var files = selectsImagesFolder(true,true); // Select the root of the Image tree and filter image file types to selected
//var files = selectsImagesFolder(false,false); // Select a folder containg Image files all image file types in the folder will be Selected
//var files = selectsImagesFolder(); // Select a folder containg Image files all image file types in the folder will be Selected
//var files = selectsImagesFolder(false,true); // Select a folder containg Image files and filter image file types to be Selected
var files = selectsImagesFolder(true,true); // Select image files
if (files!=undefined) {
fileListCopy = files; // So boilerplate can see file processes
for( var i=0; i < files.length; i++) { processFile(files[i]); } // Process Files
return files.length;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function selectsImagesFolder (multi,selection,types) { // Build a file list of selected image file types in folder
var folderList = new Array;
var fileList = new Array;
if (multi == true) {var theString = "Please select root folder"} // Process Sub Folders
else {var theString = "Please select a folder"}; // Just a single folder
var rootFolder = Folder.selectDialog(theString, ""); // Select root
if (rootFolder === null) { return}; // Test if Cancel button returns null, then do nothing
if (types!=undefined) typeList = types; // filter these
else {
var typeList = "nef|cr3|cr2|crw|dcs|raf|arw|orf|dng|psd|tif|tiff|jpg|jpe|jpeg|png|bmp"; // Get file types
if (selection == true) var typeList = prompt("Add or Remove file type to Process.",typeList); // User modifies file type selection
if (typeList === "" || typeList === null ) { return}; // Test if Cancel button returns null, then do nothing
}
fileTypes = typeList; // Add Global for boiler plate
var matchString = String("/\\.(" + typeList + ")$/i"); // Add the rest of the regular expression
folderList.push(rootFolder); // Start the Folder list at the root
if (multi == true) getFolders(rootFolder,folderList); // folderlist
getFilelist(folderList,matchString,fileList) // fileList
if (fileList=="") { return}; // Return if no files selected
function getFolders(pfolder,list) { // Recursively crawl the tree build the folder List
var dirList = pfolder.getFiles(); // Get files and sub-folders
for (var i = 0; i < dirList.length; i++) {
if (dirList[i] instanceof File) { } // Just process Folders
else {
list.push(dirList[i]); // Add to folder list
getFolders(dirList[i],list); // Add its sub-folders
};
}
}
function getFilelist(folders,filter,list) {
for( var i=0; i < folders.length; i++) { // Process folders
var files = folders[i].getFiles(eval(filter)); // Select files
for( var f=0; f < files.length; f++) {list.push(files[f]);} // Add files to selected fileList
}
}
folderListCopy = folderList; // Add Global for boiler plate
return fileList; // Return files
}
function buildFilelist () { // Build a file list of image files
var buildList = new Array;
var addfiles = selectFile(true);
if (addfiles !== null ) {
while (addfiles !== null ) {
if (addfiles.length ==1) buildList.push(addfiles);
else for( var i=0; i < addfiles.length; i++) {buildList.push(addfiles[i]);}
var addfiles = selectFile(true);
}
}
return buildList;
}
function selectFile (multi) { // Select image files only
if (multi == true) {var theString = "Please select files to be processed"}
else {var theString = "Please select a file"};
if ($.os.search(/windows/i) != -1) {var theFiles = File.openDialog (theString, '*.nef;*.cr3;*.cr2;*.crw;*.dcs;*.raf;*.arw;*.orf;*.dng;*.psd;*.psdt;*.tif;*.tiff;*.jpg;*.jpe;*.jpeg;*.png;*.bmp', multi)}
else {var theFiles = File.openDialog (theString, getFiles, multi)};
function getFiles (theFile) { ////// filter files for mac //////
if (theFile.name.match(/\.(nef|cr3|cr2|crw|dcs|raf|arw|orf|dng|psd|tif|tiff|jpg|jpe|jpeg|png|bmp)$/i) || theFile.constructor.name == "Folder") {
return true
};
};
return theFiles
};
function logInfo(Txt){ // Create write and open log file
try {
var file = new File(Folder.desktop + "/" + scriptName + " Log.txt");
file.open("w", "TEXT", "????");
file.encoding = "UTF8";
file.seek(0,2);
$.os.search(/windows/i) != -1 ? file.lineFeed = 'windows' : file.lineFeed = 'macintosh';
file.writeln(Txt);
if (file.error) alert(file.error);
file.close();
file.execute();
}
catch(e) { alert(e + ': on line ' + e.line, 'Script Error', true); }
};
function getDateTime() { // Function for returning current date and time
var date = new Date();
var dateTime = "";
if ((date.getMonth() + 1) < 10) { dateTime += "0" + (date.getMonth() + 1) + "/"; }
else { dateTime += (date.getMonth() + 1) + "/";}
if (date.getDate() < 10) { dateTime += "0" + date.getDate() + "/"; }
else { dateTime += date.getDate() + "/"; }
dateTime += date.getFullYear() + "_";
if (date.getHours() < 10) {dateTime += "0" + date.getHours() + ":"; }
else { dateTime += date.getHours() + ":"; }
if (date.getMinutes() < 10) { dateTime += "0" + date.getMinutes() + ":"; }
else { dateTime += date.getMinutes() + ":"; }
if (date.getSeconds() < 10) { dateTime += "0" + date.getSeconds(); }
else { dateTime += date.getSeconds(); }
return dateTime;
}
function timeString () { // Function for returning raw time
var now = new Date();
return now.getTime()
};
function timeStamp(){
// Get the time and format it
var digital = new Date();
var hours = digital.getHours();
var minutes = digital.getMinutes();
var seconds = digital.getSeconds();
var amOrPm = "AM";
if (hours > 11) amOrPm = "PM";
if (hours > 12) hours = hours - 12;
if (hours == 0) hours = 12;
if (minutes <= 9) minutes = "0" + minutes;
if (seconds <= 9) seconds = "0" + seconds;
// Get the date and format it
var date = new Date();
var d = date.getDate();
var day = (d < 10) ? '0' + d : d;
var m = date.getMonth() + 1;
var month = (m < 10) ? '0' + m : m;
var yy = date.getYear();
var year = (yy < 1000) ? yy + 1900 : yy;
// create a variable with the fully formatted the time and date
// todaysDate = hours + ":" + minutes + ":" + seconds + " " + amOrPm + " - " + day + "/" + month + "/" + year;
// todaysDate = hours + ":" + minutes + ":" + seconds + " " + amOrPm + " - " + month + "/" + day + "/" + year;
MonthNames = new Array("January","February","March","April","May","June","July","August","September","October","November","December");
//todaysDate = hours + ":" + minutes + ":" + seconds + " " + amOrPm + " " + MonthNames[date.getMonth()] + " " + date.getDate() + ", " + year;
todaysDate =MonthNames[date.getMonth()] + " " + date.getDate() + ", " + year +" " + hours + ":" + minutes + ":" + seconds + " " + amOrPm;
return todaysDate;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Selected file are processed here
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function processFile(file) { // Process Your files here
// Here I just parse the Files Into Path Name and Extension and Log them
// var startDate Could be used for output File Name suffix
// var scriptName could also be useful
var filePath = String(file).substr(0,String(file).lastIndexOf("/")+1);
var fileName = String(file).substr(String(file).lastIndexOf("/")+1,String(file).lastIndexOf("."));
fileName = fileName.substr(0,fileName.lastIndexOf("."));
var fileExt = String(file).substr(String(file).lastIndexOf("."));
logData = logData + filePath + "\nName: " + fileName + "\nExt : " + fileExt + "\n\n";
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// When last file is process the script will end
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Copy link to clipboard
Copied
Thanks so much!! I will give the plug-in a shot and see if I can figure out this script as well.
Copy link to clipboard
Copied
If you're not into scripting, you can still use a Batch Action.
Either install the script, then insert the script into the action... Or start recording the action, browse to the script and wait for the script to finish, then stop the recording.
Copy link to clipboard
Copied
My error I got threads mixed up
Copy link to clipboard
Copied
Easy way to include script in action is to place script in Presets > Scripts folder so you can see it in File > Scripts. WHile recording action just select script or even use Insert Menu Item to run script by action.
Copy link to clipboard
Copied
This actually worked, once I moved the script to the folder, instead of using the plug-in it came with.
However, now I have a new issue. I've successfully managed to get the action to run the script, save the file with save as, and close the file aftewards. But, Photoshop is not opening the files in order. Each file is numbered 1 through 2200. Photoshop opens file 1, then 10, then 100, then 1000, and then decides to proceed with 1002, etc etc. The Batch Process is saving them as 0001, 0002, 0003, etc, which is what I wanted, because I thought Photoshop would open the files in order.
How do I force Photoshop to open the files in order and save them sequentially as intended?
Copy link to clipboard
Copied
Copy link to clipboard
Copied
I guess I should have Googled more before posting, but figured it out. Just had to bulk rename everything to have leading 00's infront so it would run in order.
But, everything is working as intended now! And now I have a 37-48hr long batch process ahead of me. Thanks everyone for the help and pointing me in the right direction!
Copy link to clipboard
Copied
Mark the answer that helped you the much as correct solution then š
Copy link to clipboard
Copied
I have many version of Photoshop installed copying scripts to all version presets would be a maintenance nightmare. It is easier just to link Photoshop presets scripts folder to a common additional Photoshop script tree that you maintain for all versions of Photoshop you have installed. Its a Pain to use Photoshop menu File>Scripts>ScriptNameList when you have a lot of Photoshop scripts install in Photoshop. It takes forever and a day to scroll to the script you wan to use for Adobe only scrolls the list one line at a time. I run scripts from Windows File Explorer in Photoshop. I needed to add a option is my Photoshop psuserconfig.txt to get rid of the nag Adobe message about running scripts form file explorer.
# Photoshop use WinTab Stylus 0 or use INK Stylus 1
UseSystemStylus 0
# CC 2019 20.0.5 supress warning about running scripts.
WarnRunningScripts 0