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

Help with Photoshop action, script, or variable not sure

Community Beginner ,
Oct 08, 2021 Oct 08, 2021

Copy link to clipboard

Copied

I have a lot of images that I need to add dates too. 4 images get the same date and are in the same folder. There are videos in that folder too.  Attatched images is an example of what I am trying to achieve. 

 

I'd like to be able to select every jpg in a folder add the date to it and save it back to the folder with " date" appended to the end. 

 

I tried this with actions and batch to select the folder but I'm unsure how to quickly change the date for each folder so I don't have to record the text date each time. 

 

I tried this with photoshop variables but I get stuck because I have to use the title of each file and that's just as time consuming as manually adding the date. This would be a great solution if I could tell it to grab every jpg in the folder when using it instead of naming each individaul file. 

I've not familiar enough with scripts to have tried them. 

TOPICS
Actions and scripting

Views

4.2K

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
Adobe
Community Beginner ,
Oct 26, 2021 Oct 26, 2021

Copy link to clipboard

Copied

@JJMack Sorry for the delayed response. 

 

Poorly is the short answer.

I was trying to reference open documents(or files) in the subfolders of my target folder script and use it to target the folders and then make my output folder = to the array folder but it's not functioning. I'm not knowledgeable enough in javascript to do that. Hoping to learn more but at some point on this project I'm going have to spend time converting the files with the script I have instead of working on a better script. Though adding this would reduce my time by 1/3. 

 

I attached my attempt if you want to look at it. I kept getting an error and realized I'm in over my head and you all have already been so helpful I didn't want to come back and take up more of your time. 

 

#target photoshop

if (app.documents.length === 0) {

    // The "Test if Cancel..." needs to be within a function
    

		(function () {
		var folders =[];

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

if(topLevel == null) return; //if cancelled quit
			folders = FindAllFolders(topLevel, folders);  // call function FindAllFolders
			for(var z=0; z < folders.length; z++){// loop through all subfolders

        var savedDisplayDialogs = app.displayDialogs;
        var inputFolder = folders;
        var inputFiles = inputFolder.getFiles(/\.(jpg|jpeg|png)$/i);

        // var outputFolder = inputFolder;
        var outputFolder = inputFolder;
        // Test if Cancel button returns null, then do nothing
    

        var dateString = prompt("Enter the date (Month, Day Year)", "MONTH, ## ####");
        // Test if Cancel button returns null, then do nothing
        if (dateString === null) {
            app.beep();
            return;
        }

        app.displayDialogs = DialogModes.NO;

        for (var i = 0; i < inputFiles.length; i++) {
            open(inputFiles[i]);
            var docName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
            // var saveFileJPG = new File(new File(outputFolder + '/' + docName + ' ' + dateString + '.jpg'));
            var saveFileJPG = new File(new File(outputFolder + '/' + docName + ' date' + '.jpg'));
            dateStamp();
            // As this appears to be created from a template
            deleteDocumentAncestorsMetadata();
            saveJPG(saveFileJPG);
            app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
        }

        app.displayDialogs = savedDisplayDialogs;

        app.beep();
        alert("Script Completed! Files saved to: " + "\r" + outputFolder.fsName);


        /************ Functions ************/

        function dateStamp() {
            var doc = app.activeDocument;
            // Ruler units
            var origRuler = app.preferences.rulerUnits;
            app.preferences.rulerUnits = Units.POINTS;

            // Doc resolution
            var origRes = app.activeDocument.resolution;
            app.activeDocument.resizeImage(null, null, 72, ResampleMethod.NONE);

            // Text layer, based on a 72ppi resolution
            var layerRef = doc.artLayers.add();
            layerRef.name = "Date Info";
            layerRef.kind = LayerKind.TEXT;
            var textRef = layerRef.textItem;
            var textColor = new SolidColor();
            textColor.rgb.red = 255;
            textColor.rgb.green = 255;
            textColor.rgb.blue = 255;
            textRef.color = textColor;
            textRef.contents = dateString;
            textRef.position = new Array(0, 0);
            textRef.font = 'Graphik-Bold';
            textRef.size = 60;
            textRef.useAutoLeading = true;
            textRef.justification = Justification.CENTER;

		  addStyle("Bold")


            // Add drop shadow to text
            dropShadow();

            // Ruler units for positioning on canvas
            app.preferences.rulerUnits = Units.PIXELS;
            // Align text to horizontal centre
            align2SelectAll('AdCH');
            // Align text to bottom
            align2SelectAll('AdTp');
            // move text layer down
            doc.activeLayer.translate(0, 42);

            // Restore original doc resolution
            app.activeDocument.resizeImage(null, null, origRes, ResampleMethod.NONE);
            // Restore original ruler units
            app.preferences.rulerUnits = origRuler;

            function align2SelectAll(method) {
                /*
                AdLf = Align Left
                AdRg = Align Right
                AdCH = Align Centre Horizontal
                AdTp = Align Top
                AdBt = Align Bottom
                AdCV = Align Centre Vertical
                */
                doc.selection.selectAll();
                var desc = new ActionDescriptor();
                var ref = new ActionReference();
                ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
                desc.putReference(charIDToTypeID("null"), ref);
                desc.putEnumerated(charIDToTypeID("Usng"), charIDToTypeID("ADSt"), charIDToTypeID(method));
                try {
                    executeAction(charIDToTypeID("Algn"), desc, DialogModes.NO);
                } catch (e) { }
                doc.selection.deselect();
            }
        }

        function saveJPG(saveFileJPG) {
            var jpgOptions = new JPEGSaveOptions();
            jpgOptions.formatOptions = FormatOptions.STANDARDBASELINE;
            jpgOptions.embedColorProfile = true;
            jpgOptions.matte = MatteType.NONE;
            jpgOptions.quality = 12;
            app.activeDocument.saveAs(saveFileJPG, jpgOptions, true, Extension.LOWERCASE);
        }

        function deleteDocumentAncestorsMetadata() {
            // https://prepression.blogspot.com/2017/06/metadata-bloat-photoshopdocumentancestors.html
            // https://forums.adobe.com/message/8456985#8456985
            if (ExternalObject.AdobeXMPScript === undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
            var xmp = new XMPMeta(activeDocument.xmpMetadata.rawData);
            xmp.deleteProperty(XMPConst.NS_PHOTOSHOP, "DocumentAncestors");
            app.activeDocument.xmpMetadata.rawData = xmp.serialize();
        }



        function dropShadow() 
	{

	var idset = stringIDToTypeID( "set" );
    var desc7 = new ActionDescriptor();
    var idnull = stringIDToTypeID( "null" );
        var ref1 = new ActionReference();
        var idproperty = stringIDToTypeID( "property" );
        var idlayerEffects = stringIDToTypeID( "layerEffects" );
        ref1.putProperty( idproperty, idlayerEffects );
        var idlayer = stringIDToTypeID( "layer" );
        var idordinal = stringIDToTypeID( "ordinal" );
        var idtargetEnum = stringIDToTypeID( "targetEnum" );
        ref1.putEnumerated( idlayer, idordinal, idtargetEnum );
    desc7.putReference( idnull, ref1 );
    var idto = stringIDToTypeID( "to" );
        var desc8 = new ActionDescriptor();
        var idscale = stringIDToTypeID( "scale" );
        var idpercentUnit = stringIDToTypeID( "percentUnit" );
        desc8.putUnitDouble( idscale, idpercentUnit, 416.666667 );
        var iddropShadow = stringIDToTypeID( "dropShadow" );
            var desc9 = new ActionDescriptor();
            var idenabled = stringIDToTypeID( "enabled" );
            desc9.putBoolean( idenabled, true );
            var idpresent = stringIDToTypeID( "present" );
            desc9.putBoolean( idpresent, true );
            var idshowInDialog = stringIDToTypeID( "showInDialog" );
            desc9.putBoolean( idshowInDialog, true );
            var idmode = stringIDToTypeID( "mode" );
            var idblendMode = stringIDToTypeID( "blendMode" );
            var idmultiply = stringIDToTypeID( "multiply" );
            desc9.putEnumerated( idmode, idblendMode, idmultiply );
            var idcolor = stringIDToTypeID( "color" );
                var desc10 = new ActionDescriptor();
                var idred = stringIDToTypeID( "red" );
                desc10.putDouble( idred, 0.000000 );
                var idgrain = stringIDToTypeID( "grain" );
                desc10.putDouble( idgrain, 0.000000 );
                var idblue = stringIDToTypeID( "blue" );
                desc10.putDouble( idblue, 0.000000 );
            var idRGBColor = stringIDToTypeID( "RGBColor" );
            desc9.putObject( idcolor, idRGBColor, desc10 );
            var idopacity = stringIDToTypeID( "opacity" );
            var idpercentUnit = stringIDToTypeID( "percentUnit" );
            desc9.putUnitDouble( idopacity, idpercentUnit, 35.000000 );
            var iduseGlobalAngle = stringIDToTypeID( "useGlobalAngle" );
            desc9.putBoolean( iduseGlobalAngle, true );
            var idlocalLightingAngle = stringIDToTypeID( "localLightingAngle" );
            var idangleUnit = stringIDToTypeID( "angleUnit" );
            desc9.putUnitDouble( idlocalLightingAngle, idangleUnit, 90.000000 );
            var iddistance = stringIDToTypeID( "distance" );
            var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
            desc9.putUnitDouble( iddistance, idpixelsUnit, 8.000000 );
            var idchokeMatte = stringIDToTypeID( "chokeMatte" );
            var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
            desc9.putUnitDouble( idchokeMatte, idpixelsUnit, 42.000000 );
            var idblur = stringIDToTypeID( "blur" );
            var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
            desc9.putUnitDouble( idblur, idpixelsUnit, 139.000000 );
            var idnoise = stringIDToTypeID( "noise" );
            var idpercentUnit = stringIDToTypeID( "percentUnit" );
            desc9.putUnitDouble( idnoise, idpercentUnit, 0.000000 );
            var idantiAlias = stringIDToTypeID( "antiAlias" );
            desc9.putBoolean( idantiAlias, false );
            var idtransferSpec = stringIDToTypeID( "transferSpec" );
                var desc11 = new ActionDescriptor();
                var idname = stringIDToTypeID( "name" );
                desc11.putString( idname, """Linear""" );
            var idshapeCurveType = stringIDToTypeID( "shapeCurveType" );
            desc9.putObject( idtransferSpec, idshapeCurveType, desc11 );
            var idlayerConceals = stringIDToTypeID( "layerConceals" );
            desc9.putBoolean( idlayerConceals, true );
        var iddropShadow = stringIDToTypeID( "dropShadow" );
        desc8.putObject( iddropShadow, iddropShadow, desc9 );
    var idlayerEffects = stringIDToTypeID( "layerEffects" );
    desc7.putObject( idto, idlayerEffects, desc8 );
executeAction( idset, desc7, DialogModes.NO );

  	}

function addStyle(Style){
	var idASty = charIDToTypeID( "ASty" );
	    var desc20 = new ActionDescriptor();
	    var idnull = charIDToTypeID( "null" );
	        var ref3 = new ActionReference();
	        var idStyl = charIDToTypeID( "Styl" );
	        ref3.putName( idStyl, Style );
	    desc20.putReference( idnull, ref3 );
	    var idT = charIDToTypeID( "T   " );
	        var ref4 = new ActionReference();
	        var idLyr = charIDToTypeID( "Lyr " );
	        var idOrdn = charIDToTypeID( "Ordn" );
	        var idTrgt = charIDToTypeID( "Trgt" );
	        ref4.putEnumerated( idLyr, idOrdn, idTrgt );
	    desc20.putReference( idT, ref4 );
	try{
		executeAction( idASty, desc20, DialogModes.NO);
	}catch(e){}
}


    };
		}
		 
		 
		  })();
		 
		 
 else {
    alert('No documents should be open when running this script!');
}

 

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 ,
Oct 26, 2021 Oct 26, 2021

Copy link to clipboard

Copied

What you posted is bad its incompler and mess up the firts function it use is missing.  Pgitsop scprts put out an error

image.png

folders = FindAllFolders(topLevel, folders); // call function FindAllFolders

 

The  FindAllFolders fubction is not in your post and the ends of the script look all messed up

image.png

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
Community Expert ,
Oct 26, 2021 Oct 26, 2021

Copy link to clipboard

Copied

Here is a script I put the together it has a few function I wrote to build File List to process.  The functions should be easy to use to build you list of files,   The is a parameter that you can set  to true to process sub folders. The function will recursively use itself. There are also file type filtering parameters that cans be used. I have a demo script  that can build file lists many ways  using these functions,  It only takes one line of code to build the file list you want to create.  So in the demo I have  code several of these one line file list creators.   They are all comment ant the are all  commented out but one the one to want  to text.  The demo process the file list you build. All the process does is toe created a log of the files paths..  It could just as easily opened the files and process them. Just look at the Main...

image.png

 

Here is the script with the functions...

/* =======================================================================
// 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
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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
Community Beginner ,
Nov 15, 2021 Nov 15, 2021

Copy link to clipboard

Copied

JjMack,

Thanks for the script. I'm now finished with my project but still want to learn. I've started going through some javascript courses. And am excited to keep learning and applying these to projects going forward in photoshop. I do a lot of task that are repetitive and I'm hoping to write some scripts to reduce time. Thanks again for all your help!

 

I was able to run your script and get the results printed of all the folders. I was not however able to pass those variables into Stephen's script and I'm perplexed. I'll continue to come back to this script as I'm learning more to see how to get these to pass through, I tried using some of your global variables in replacement of some of Stephen's to no avail.  

 

Do you have any advice on code editors to help me see where the code is stopping? I'm currently running it in Photoshop. I'm not getting any errors so the syntax is correct but the code is incorrect because I'm not getting any results.

 

I'm writing/editing in Dreamweaver and then running it in photoshop. 

 

 

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 ,
Nov 15, 2021 Nov 15, 2021

Copy link to clipboard

Copied

Adobe recommends using Microsoft Visual Studio Code for editing, there are some Extendscript-specific plugins available to make things easier.

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 ,
Nov 15, 2021 Nov 15, 2021

Copy link to clipboard

Copied

I only hack at Photoshop Scripting.   I'm a retired programmer I was never prolific programmer. I can type or spell never went to programming school.  However, it turned out  I was good at debugging, designing and developing programing development tools so I made a decent living as a Programmer for 30+ years.   

 

To script Photoshop you need to understand how Photoshop works well so you can design processes  to accomplish what you want to do.  Photoshop Scripting DOM does not cover all of Photoshop features.   Most Scripts need to include some Action Manager code  to accoplish what need to be done.

 

Adobe has a Photoshop plug-in Scriptlistener  that is like an Action recorder that records the steps you do in Photoshop into two log files on your desktop. One is log is  JavaScript Code the other VSB code all that can be recorded is recorded there are no controls.  The coed is like action step.  All settings are hard coded the is noe logic. You need to add the logic and variable settings.  The code is not easy to read and its also one sided as far as the action manager goes. The execute side  of  the Action Manger  the manger other side can retrieve information about Photoshop and documents states.   Because I do know JaveScript or much about  objects.   I have very hard time scripting Photoshop. 

 

At my age it to teach myself all that is required is not worthwhile for me.   I'm content at being able to hack some simple processes like  Collages, Mockup placing logos etcs. senility could bet around the corner hacking slows my progress around the corner.

 

There is very few Photoshop scripting resource the are a few books .  Reading the code in Adobe sample script is a good starting point as is reading code in Photoshop Scripts folder.  Some of them are over my head .  However  I would state Fit Image JSX is a very good and relatively easy  example for  creating Dialogs and Photoshop Plug-in  in using Javs script.  I stole the code in Fit image to create my AspecctRatioSelection  and LongPrintSide  plug-ins to be use in actions.    The forum is the resource I turn to most.

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
Community Beginner ,
Nov 15, 2021 Nov 15, 2021

Copy link to clipboard

Copied

Thanks! The advice by @Lumigraphics helped me get a code software that is showing me were the breakdown in the code is. Which will make learning and tinkering to get this to work more manageable for me. I am a designer for many years and do some web coding. I'm excited to be able to dive into javascript and be able to apply it in photoshop and web. 

 

I'm pretty familiar with actions but they don't often have the logic I need. This blog has been great and you @JJMack have been a great help. I hope to post my code here when I conquer getting these too to work together! 

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 ,
Nov 15, 2021 Nov 15, 2021

Copy link to clipboard

Copied

LATEST

Scripts can be use in Actions so some very small trivial scripts use in actions can add some logic into actions, Run twice scripts can save things for actions the action can the make changes then use the use the script a second  time to restore saved things. So a little scripting can go a long way.

 

It is ease to record actions. Scripts can also use Actions look at  how powerful Image Processor Pro

can be when you add simple lithe actions to it run.  Inage Processor Pro... is A Photoshop Plug_in it supports itself  being recorded into actions. adding a messaget to be set to itsself  when the action is played 

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
Community Expert ,
Oct 13, 2021 Oct 13, 2021

Copy link to clipboard

Copied

Stephen recursion can be hard to get a grip on. You may want to look at Adobe Script Image Processor.  It has  an option to process subfolder Images and also to keep the structure in the output folder.

 

Here is a sample of recursion code used to process a document layer stack.  The function processArtLayers is used recursively to process layers in an object. The script is as simple as I can make it. What you need to understand  is the Function varable are local there is not one obj array every recursion of  processArtLayers has its own local obj array. Only var allLayers is global. The first processArtLayers used in main is the last to end  You may want to run this script on a few different structure Photoshop documents.  The order the image layers are processed may surprise you

 

 

 

// declare Global variables
var allLayers = ""; 
main();
alert(allLayers);
function main() {
	processArtLayers(activeDocument) 
}
function processArtLayers(obj) {  
    for( var i = obj.artLayers.length-1; 0 <= i; i--) {/* alert(obj.artLayers[i]); */processLayers(obj.artLayers[i])}  
    for( var i = obj.layerSets.length-1; 0 <= i; i--) {/* alert(obj.layerSets[i]); */processArtLayers(obj.layerSets[i])} // Process Layer Set Layers  
} 
function processLayers(layer) { 
	//alert('Layer Name = "' + layer.name + '" Layer Kind ' + layer.kind );
	allLayers = allLayers + "ID " + layer.id + ", " + layer.name + ", " + layer.kind + "\n";
}

 

 

 

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
Community Expert ,
Oct 11, 2021 Oct 11, 2021

Copy link to clipboard

Copied

Sheaffer

You have Stephen's script to work from. If you want it to also process  all lower subfolders he replied to you that a recursive process. The script will need to handle the entire folder selected process the Jpeg  and recursively process all folders.  However, the current  process would need to be to be modified to handle the recursion,  For the output files for each subfolder  would also need to be saved into subfolders  for the dated jpegs.   I my opinion you should try the make the modification.  Stephen likes to help but he is not your employee you should reward him with at least some good praise. 

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
Community Expert ,
Oct 09, 2021 Oct 09, 2021

Copy link to clipboard

Copied

The script look good. It could be improved some by adding a drop  shadow on the text layer for white on white does not show the text. Also the text size  should probably be set relative to the width of the document so the text will fit in narrow documents. Also  the save file name  you added a suffix  ' date' not the entered date. I'm not sure which the OP wants.

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
Community Expert ,
Oct 09, 2021 Oct 09, 2021

Copy link to clipboard

Copied

@JJMack – thank you!

 

I personally prefer using the following for white on white;

 

layerRef.blendMode = BlendMode.DIFFERENCE;

 

I decided not to do that and some of the other things that I did in Print metadata on bottom of photo that you mention which I have done in the past, until there is some feedback.

 

I asked @Sheaffer about the ' date' suffix, that is easily changed,.. However, if you re-read the post and look at both of the attached filenames ' date' seems appropriate for now.

 

There is always room for adjustments, this is only a v1.0 script after all.

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 ,
Oct 08, 2021 Oct 08, 2021

Copy link to clipboard

Copied

When using variables and data sets you can not rename files. Also when using data sets you can export or save files only in PSD file format. There are other ways to append to file name but the question is whether you want word date, actual date or both as already asked by @Stephen Marsh 

You can also count on variables to add text and some other way to append whatever you want to file name while converting PSD to desired output format.

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 ,
Oct 26, 2021 Oct 26, 2021

Copy link to clipboard

Copied

Could you use Batch Rename in Bridge?

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