Copy link to clipboard
Copied
Hi experts
I am writing a adobe photoshop script where I can select the folder name from the dialog window and the script will open the very first image from that folder. I will edit the picture and only when I save and close the image, the second image will be opened. And the same thing will continue. So the script will open only one image at a time. How this is possible?
I was doing with many experiments and the current code is like this.
var imageFolder = new Folder("C:/Nirmalya/Photo/");
function filter(file) {
return (file instanceof File && /\.(jpg)$/i.test(file.name))
}
var fileList = imageFolder.getFiles(filter);
if (fileList.length > 0) {
//Sort the fileList
fileList.sort(function (a, b) {
if (app.compareWithNumbers) {
return app.compareWithNumbers(a.name, b.name);
} else {
return sortAlphaNum(a.name, b.name);
}
});
loop:
for (var index1 = 0; index1 < fileList.length; index1++) {
if (documents.length<1) {
alert("1");
open(fileList[index1]);
}
else {
do {
// nothing
} while (documents.length==1);
alert("2");
continue loop;
}
}
}
But photoshop is hanging in the do while block. It's not allowing me to do any operation on the open file.
If I don't use this block, then while the first image is opened, the loop is actually iterating the entire loop, and after the first image is closed, no other image is opened.
I know that there is an autoloaded utility. But I don't need that complex tool, I need to open only one image at a time.
What could be relevant code from the autoloaded tool that will serve my purpose?
Many thanks in advance ...
I don't think this is really possible or practical, for the reasons you found out. When a script runs, it will tie up PS until it finishes. A workaround might be to write a script that creates a text file of all the files paths names from a folder that you want to process. Then create another script that opens the next file, by assigning a F number hot key. You can control which file is next by having the script either delete the reference path from the text file or having another text file with
...'This is a tricky one to answer...
What Stephen said about zimonitrome's script is probably the fastest solution given that:
- you don't want the autoloader utility
- you need an autoloader but not a complex one
The hardest part I think will be to give up on the functionality you might want to have so you can use zimo's script.
You could rewrite zimo's script so it looks for a different filename pattern, maybe that helps you out well enough?
For something generalized & homemade, you'll probably nee
...Hi, first of many thanks to all the great minds in this community. They suggested me how to simulate this automatic open close feature with the help of scripts. I have attached the scripts herewith, I have also attached the screenshot of how to add the script in the Scripts Event Manager tab.
SequentialOpenFiles.jsx - This is the main script with multi-file selection dialog. The user needs to select the files in the drop down list. All the image files are supported. This script will create a text
Copy link to clipboard
Copied
I don't think this is really possible or practical, for the reasons you found out. When a script runs, it will tie up PS until it finishes. A workaround might be to write a script that creates a text file of all the files paths names from a folder that you want to process. Then create another script that opens the next file, by assigning a F number hot key. You can control which file is next by having the script either delete the reference path from the text file or having another text file with an index number.
Copy link to clipboard
Copied
From what I know, it isn't easy... It has been asked many times and I don't know of a "free" answer:
https://www.photoshoptools.ca/photo-workflow/autoloader/
Copy link to clipboard
Copied
This script works with files with a specific name pattern of 5 zero-padded digits. Start with the first doc open and then run the script after editing to save, close and open the next file for editing from the same folder:
00001.tif
00002.tif
00003.tif
https://gist.github.com/zimonitrome/eb70f99c45a05231bf20d4e562106568
var folderPath = activeDocument.path
var filePieces = activeDocument.name.split('.');
var fileName = filePieces[0];
var fileExtension = filePieces[1];
// We need to unpad the string for some reason, otherwise PS-JS
// thinks it's a past layer some times when using parseInt.
fileNameStart = 0;
for (var i = 0; i < fileName.length - 1; i++) {
digit = fileName[i];
if (digit == '0') {
fileNameStart++;
} else {
break
};
}
fileNameUnpadded = fileName.slice(fileNameStart);
var nextFileNumber = parseInt(fileNameUnpadded) + 1;
// Yes it's haxxy I know...
var padTemp = ("000000000000000" + nextFileNumber.toString());
var nextFileName = padTemp.slice(padTemp.length - 5);
var nextFilePath = folderPath + '/' + nextFileName + '.' + fileExtension;
activeDocument.close(SaveOptions.SAVECHANGES);
try {
var docRef = open(new File(nextFilePath));
}
catch (e) {
alert("No more files in the directory!");
}
Copy link to clipboard
Copied
'This is a tricky one to answer...
What Stephen said about zimonitrome's script is probably the fastest solution given that:
- you don't want the autoloader utility
- you need an autoloader but not a complex one
The hardest part I think will be to give up on the functionality you might want to have so you can use zimo's script.
You could rewrite zimo's script so it looks for a different filename pattern, maybe that helps you out well enough?
For something generalized & homemade, you'll probably need to get your hands dirty like Chuck said.
Ie, make a script that controls the Script Events Manager (File > Scripts > Script Events Manager) and a script you can attach to the close event when the user runs your script. These 2 scripts, one control script and one 'procedure' script.
The control script generates the list of files to treat + source & destination directories, the behavior script attached to the close event executes the behavior you want from it. Ie: on closing, look in the temp file, load the next file location, update the list, open the next file. Depending on how fancy you want to go, you can improve on this solution with extra steps and behaviors.
Apologies for the rehash, I hope it offers you extra perspective on the answers given.
Copy link to clipboard
Copied
I have cracked the problem and written two scripts which will resove the issue.
Am I allowed to upload the full solution code?
Copy link to clipboard
Copied
of course you can indeed it would be useful to many.
Copy link to clipboard
Copied
Please use the forum post software toolbar ... icon and then the code icon </> to enter the code.
Copy link to clipboard
Copied
Hi, first of many thanks to all the great minds in this community. They suggested me how to simulate this automatic open close feature with the help of scripts. I have attached the scripts herewith, I have also attached the screenshot of how to add the script in the Scripts Event Manager tab.
SequentialOpenFiles.jsx - This is the main script with multi-file selection dialog. The user needs to select the files in the drop down list. All the image files are supported. This script will create a text file in the C:\Users\<username>\AppData\Roaming\Adobe\Adobe Photoshop XXXX\Adobe Photoshop XXXX Settings\ directory. That text file will contain the list of all the files selected in the above selection operation (except the very first file). This script will open the very first first file. Successive files will be opened by the event listener script.
function createOpenDialog() {
try {
var fileList;
// DIALOG
// ======
var openDialog = new Window("dialog");
openDialog.text = "Sequential Image Open";
openDialog.orientation = "column";
openDialog.alignChildren = ["center","top"];
openDialog.spacing = 10;
openDialog.margins = 16;
// PANEL1
// ======
var panel1 = openDialog.add("panel", undefined, undefined, {name: "panel1"});
panel1.orientation = "column";
panel1.alignChildren = ["left","top"];
panel1.spacing = 10;
panel1.margins = 10;
var statictext1 = panel1.add("statictext", undefined, undefined, {name: "statictext1"});
statictext1.text = "Please select the images";
// GROUP1
// ======
var group1 = panel1.add("group", undefined, {name: "group1"});
group1.orientation = "row";
group1.alignChildren = ["left","center"];
group1.spacing = 10;
group1.margins = 0;
var edittext1 = group1.add('edittext {properties: {name: "edittext1"}}');
edittext1.helpTip = "Please select the image files";
edittext1.preferredSize.width = 500;
var button1 = group1.add("button", undefined, undefined, {name: "button1"});
button1.text = "Select ...";
button1.onClick = function() {
if ($.os.search(/windows/i) != -1) {
fileList = File.openDialog ("Please select the image files" , '*.jpg;*.jpeg;*.tif;*.psd;*.png;*.bmp', true);
}
else {
fileList = File.openDialog("Please select the image files", getFiles, true)
};
var fileNames=[];
for (var i=0;i<fileList.length;i++) {
fileNames[i]=fileList[i].fsName;
}
edittext1.text=fileNames;
}
function getFiles(theFile) {
if (theFile.name.match(/\.(txt|csv)$/i) || theFile.constructor.name == "Folder") {
return true
};
};
// PANEL2
// ======
var panel2 = openDialog.add("panel", undefined, undefined, {name: "panel2"});
panel2.orientation = "column";
panel2.alignChildren = ["left","top"];
panel2.spacing = 10;
panel2.margins = 10;
// GROUP2
// ======
var group2 = panel2.add("group", undefined, {name: "group2"});
group2.orientation = "row";
group2.alignChildren = ["left","center"];
group2.spacing = 10;
group2.margins = 0;
var button2 = group2.add("button", undefined, undefined, {name: "button2"});
button2.text = "Start";
button2.onClick = function () {
if (edittext1.text.length==0) {
alert("Please select the image files");
return;
}
openDialog.close();
createListFile(fileList);
}
var button3 = group2.add("button", undefined, undefined, {name: "button3"});
button3.text = "Cancel";
// openDialog.show();
openDialog.center();
return openDialog;
}
catch(e) {
alert(e + ': Line ' + e.line);
}
}
function showDialog(myDialog) {
return myDialog.show();
}
main()
function main() {
var openDialog = createOpenDialog();
showDialog(openDialog);
}
function createListFile(fileList) {
try {
if (fileList.length > 0) {
//Sort the fileList
fileList.sort(function (a, b) {
if (app.compareWithNumbers) {
return app.compareWithNumbers(a.name, b.name);
} else {
return sortAlphaNum(a.name, b.name);
}
});
var listFile = new File( app.preferencesFolder + "/" + "OpenClose_FileList.txt" );
listFile.open("a");
for (var index1 = 1; index1 < fileList.length; index1++) {
listFile.writeln(fileList[index1]);
}
listFile.close();
//Open the first file
open(fileList[0]);
}
}
catch(e) {
alert(e + ': Line ' + e.line);
}
}
CloseEventListener.jsx - this file should be selected in the Scripts Event Manager tab for Close Document event. So whenever any document will be closed, this script will open the successive file from the above mentioned file list. I have emphasised any because even if a file is opened which is not in the list and then closed, the event will be triggered and the first file from the file list will be opened. After due editing, whenever the file will be closed, this script will delete the first line from the text file. And the operation will continue.
var listFile = new File( app.preferencesFolder + "/" + "OpenClose_FileList.txt" );
listFile.open("r");
var contents = listFile.read();
listFile.close();
var rows = processInputFile(contents);
if (rows.length>0) {
var file = new File(rows[0]);
open(file);
//delete first line
listFile.open("w");
for (var i=1;i<rows.length;i++) {
listFile.writeln(rows[i]);
}
listFile.close();
}
function processInputFile(contents) {
try {
// Returns: Array [row][column]
var c = ""; // Character at index.
var index = 0;
var maxIndex = contents.length - 1;
var result = []; // Array of rows.
var row = []; // Array of columns.
var rowSum = 0; // Count of row contents.
var v = ""; // Column value.
while (index < contents.length) {
c = contents[index];
if (c == "\n" || c == "\r") {
// Reached end of line.
// Test for CRLF.
if (c == "\r" && index < maxIndex) {
if (contents[index + 1] == "\n") {
// Skip trailing newline.
index++;
}
}
// Column and row complete.
row.push(v);
rowSum += v.length;
if (rowSum) {
// Add row only when it has content.
result.push(row);
}
v = "";
row = [];
rowSum = 0;
}
else {
// Add character to column value.
v += c;
//alert(c);
}
if (index == maxIndex) {
// Reached end of data; flush.
row.push(v);
rowSum += v.length;
if (rowSum) {
// Add row only when it has content.
result.push(row);
}
break;
}
index++;
}
return result;
}
catch(e) {
alert(e + ': Line ' + e.line);
}
}
This way the user has to register the event listener file in Photoshop Scripts Event Manager tab -
At anytime if the user wants to break the operation, he has to simply uncheck the Enable ... checkbox.
Hope this helps.
Thanks
Nirmalya
Copy link to clipboard
Copied
a great job I'll try it as soon as possible to see if it works with Mac too.
Copy link to clipboard
Copied
@nirmalya123 – Great stuff, thank you for sharing!
I tested on a Mac and had to change the following line from Folder
if (theFile.name.match(/\.(txt|csv)$/i) || theFile.constructor.name == "Folder") {
To File
if (theFile.name.match(/\.(txt|csv)$/i) || theFile.constructor.name == "File") {
Copy link to clipboard
Copied
Yes, sorry for the mistake! Actually it was copy paste from another piece of code where I was accepting input from a folder dialog window.
In fact the line should be -
if (theFile.name.match(/\.(jpg|jpeg|tif|psd|png|bmp)$/i) || theFile.constructor.name == "File") {
Thanks for testing in Mac and correcting my mistake.
Copy link to clipboard
Copied
As an alternative to using two separate scripts and the Script Events Manager, I have combined the code into a single script.
Hold down the ALT or OPT modifier key when first running the script to set the file list via the GUI.
Run the same script without the modifier key to automatically close/save the currently open file and open the next file.
I changed the TXT file location to the desktop for my testing, the code can be changed back to the original script location if required.
Once installed, the script can be added to Edit > Keyboard Shortcuts > Scripts for easy access/usage.
/*
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-open-a-number-of-images-but-one-at-a-time/td-p/13794488
*/
#target photoshop
/* Hold down the ALT/OPT key to set the GUI */
if (ScriptUI.environment.keyboardState.altKey) {
function createOpenDialog() {
try {
var fileList;
// DIALOG
// ======
var openDialog = new Window("dialog");
openDialog.text = "Sequential Image Open";
openDialog.orientation = "column";
openDialog.alignChildren = ["center", "top"];
openDialog.spacing = 10;
openDialog.margins = 16;
// PANEL1
// ======
var panel1 = openDialog.add("panel", undefined, undefined, {
name: "panel1"
});
panel1.orientation = "column";
panel1.alignChildren = ["left", "top"];
panel1.spacing = 10;
panel1.margins = 10;
var statictext1 = panel1.add("statictext", undefined, undefined, {
name: "statictext1"
});
statictext1.text = "Please select the images";
// GROUP1
// ======
var group1 = panel1.add("group", undefined, {
name: "group1"
});
group1.orientation = "row";
group1.alignChildren = ["left", "center"];
group1.spacing = 10;
group1.margins = 0;
var edittext1 = group1.add('edittext {properties: {name: "edittext1"}}');
edittext1.helpTip = "Please select the image files";
edittext1.preferredSize.width = 500;
var button1 = group1.add("button", undefined, undefined, {
name: "button1"
});
button1.text = "Select ...";
button1.onClick = function () {
if ($.os.search(/windows/i) != -1) {
fileList = File.openDialog("Please select the image files", '*.jpg;*.jpeg;*.tif;*.tiff;*.psd;*.psb;*.png;*.bmp', true);
} else {
fileList = File.openDialog("Please select the image files", getFiles, true)
};
var fileNames = [];
for (var i = 0; i < fileList.length; i++) {
fileNames[i] = fileList[i].fsName;
}
edittext1.text = fileNames;
}
function getFiles(theFile) {
if (theFile.name.match(/\.(jpg|jpeg|tif|tiff|psd|psb|png|bmp)$/i) || theFile.constructor.name == "File") {
return true
};
};
// PANEL2
// ======
var panel2 = openDialog.add("panel", undefined, undefined, {
name: "panel2"
});
panel2.orientation = "column";
panel2.alignChildren = ["left", "top"];
panel2.spacing = 10;
panel2.margins = 10;
// GROUP2
// ======
var group2 = panel2.add("group", undefined, {
name: "group2"
});
group2.orientation = "row";
group2.alignChildren = ["left", "center"];
group2.spacing = 10;
group2.margins = 0;
var button2 = group2.add("button", undefined, undefined, {
name: "button2"
});
button2.text = "Start";
button2.onClick = function () {
if (edittext1.text.length == 0) {
alert("Please select the image files");
return;
}
openDialog.close();
createListFile(fileList);
}
var button3 = group2.add("button", undefined, undefined, {
name: "button3"
});
button3.text = "Cancel";
// openDialog.show();
openDialog.center();
return openDialog;
} catch (e) {
alert(e + ': Line ' + e.line);
}
}
function showDialog(myDialog) {
return myDialog.show();
}
main()
function main() {
var openDialog = createOpenDialog();
showDialog(openDialog);
}
function createListFile(fileList) {
try {
if (fileList.length > 0) {
//Sort the fileList
fileList.sort(function (a, b) {
if (app.compareWithNumbers) {
return app.compareWithNumbers(a.name, b.name);
} else {
return sortAlphaNum(a.name, b.name);
}
});
var listFile = new File("~/Desktop" + "/" + "OpenClose_FileList.txt");
listFile.open("a");
for (var index1 = 1; index1 < fileList.length; index1++) {
listFile.writeln(fileList[index1]);
}
listFile.close();
//Open the first file
open(fileList[0]);
}
} catch (e) {
alert(e + ': Line ' + e.line);
}
}
/* Close and open the next doc */
} else {
var listFile = File("~/Desktop" + "/" + "OpenClose_FileList.txt");
if (File(listFile).exists) {
//activeDocument.close(SaveOptions.PROMPTTOSAVECHANGES);
activeDocument.close(SaveOptions.SAVECHANGES);
listFile.open("r");
var contents = listFile.read();
listFile.close();
var rows = processInputFile(contents);
if (rows.length > 0) {
var file = new File(rows[0]);
open(file);
//delete first line
listFile.open("w");
for (var i = 1; i < rows.length; i++) {
listFile.writeln(rows[i]);
}
listFile.close();
}
} else {
alert("Run the script again with the ALT/OPT key depressed!");
activeDocument.close(SaveOptions.PROMPTTOSAVECHANGES);
}
function processInputFile(contents) {
try {
// Returns: Array [row][column]
var c = ""; // Character at index.
var index = 0;
var maxIndex = contents.length - 1;
var result = []; // Array of rows.
var row = []; // Array of columns.
var rowSum = 0; // Count of row contents.
var v = ""; // Column value.
while (index < contents.length) {
c = contents[index];
if (c == "\n" || c == "\r") {
// Reached end of line.
// Test for CRLF.
if (c == "\r" && index < maxIndex) {
if (contents[index + 1] == "\n") {
// Skip trailing newline.
index++;
}
}
// Column and row complete.
row.push(v);
rowSum += v.length;
if (rowSum) {
// Add row only when it has content.
result.push(row);
}
v = "";
row = [];
rowSum = 0;
} else {
// Add character to column value.
v += c;
//alert(c);
}
if (index == maxIndex) {
// Reached end of data; flush.
row.push(v);
rowSum += v.length;
if (rowSum) {
// Add row only when it has content.
result.push(row);
}
break;
}
index++;
}
return result;
} catch (e) {
alert(e + ': Line ' + e.line);
}
}
}
Copy link to clipboard
Copied
This is some pretty sweet stuff! Well done!
One suggestion (kinda) is to keep the supposed currently active document as first line in the text file, the next file in line thus being the second line in the text file. With this, you can check if the currently active document is in the list or not.
This will permit the user to work on a list, but also to work on another file ad-hoc and then continue where the user left off.
If it's in the list, then trigger the 'load next document in the list' behavior; else, then do nothing.
I used to have to retouche +500 images a day but also get random requests during the day to adjust a random image asap. Having this option would have greatly helped in this case.
Seeing as you already have a dialog, maybe you could consider turning this into a uxp plugin? 😄
Copy link to clipboard
Copied
I had forgotten about this, however, the "Advanced Batch" script from @jazz-y can open one file at a time and keep track of the next file from the input folder the next time that the script is run, until all input folder files are processed:
https://github.com/boogalooper/Advanced-batch/blob/master/readme.md
Copy link to clipboard
Copied
Oops, saw this thread too late...
Such script was written around 2005–2007 and might still be out there on the PS Scripts forum.
I think it was AH next image (Andrew Hall).
It would probably need some changes to work again.
I'd agree it's essential and should come with PS.
- - -
Upd.: This was one spot. It offered choice of loading by number or by date.
Copy link to clipboard
Copied
Sadly there is no code and it appears that the attachment was lost when the psscripts site was resurrected.
Copy link to clipboard
Copied
Another option from @r-bin (requires an open document to open the next document):
Copy link to clipboard
Copied
Another option, this script will open 1, 2 or more sets of images at a time and keep track of them until all images in the folder have been processed.
/*
Open Sequential Set of N Files v1-1.jsx
Stephen Marsh
v1.0, 9th November 2024
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-open-a-number-of-images-but-one-at-a-time/m-p/13804564
Related topics:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/reveal-in-explorer-js/td-p/14967762
https://community.adobe.com/t5/photoshop-ecosystem-discussions/when-i-open-more-than-50-images-in-photoshop-2022-the-photoshop-behaviour-is-changed/m-p/12850988
https://community.adobe.com/t5/photoshop-ecosystem-discussions/workflow-quot-auto-load-quot-images-from-a-file-directory-to-edit-one-at-a-time/m-p/9084727
*/
#target photoshop
var settingsFilePath = Folder(app.preferencesFolder);
var settingsFile = File(settingsFilePath + "/" + "Open Sequential Set of N Files Settings.json");
openNextFiles();
function showMainDialog() {
var settings = readSettings();
var dialog = new Window("dialog", "Open Sequential Set of N Files (v1.1)");
dialog.orientation = "column";
dialog.alignChildren = ["fill", "top"];
dialog.preferredSize.width = 450;
// Main panel with buttons and text fields
var mainPanel = dialog.add("panel");
mainPanel.alignChildren = "left";
mainPanel.margins = 15;
// Folder selection and path display with truncation
var folderGroup = mainPanel.add("group");
folderGroup.orientation = "row";
var selectFolderButton = folderGroup.add("button", undefined, "Select Folder");
var folderPathText = folderGroup.add("statictext", undefined, settings.folderPath ? truncatePath(settings.folderPath) : "No folder selected");
folderPathText.characters = 60;
// Quantity input
mainPanel.add("statictext", undefined, "Number of files to open each time:");
var quantityInput = mainPanel.add("edittext", undefined, settings.quantity || "1");
quantityInput.characters = 5;
quantityInput.preferredSize.width = 120;
// Checkboxes for additional options
var reverseOrderCheckbox = mainPanel.add("checkbox", undefined, "Open files in reverse order");
reverseOrderCheckbox.value = settings.reverseOrder || false;
var setFirstFileActiveCheckbox = mainPanel.add("checkbox", undefined, "Make the first file in set the active document");
setFirstFileActiveCheckbox.value = settings.setFirstFileActive || false;
// Disable setFirstFileActiveCheckbox if quantity is 1 initially
setFirstFileActiveCheckbox.enabled = parseInt(quantityInput.text, 10) !== 1;
// Event listener to disable the checkbox based on quantity input
quantityInput.onChanging = function () {
var quantity = parseInt(quantityInput.text, 10);
setFirstFileActiveCheckbox.enabled = quantity !== 1;
};
// Cancel and OK buttons
var btnGroup = dialog.add("group");
btnGroup.alignment = "right";
var cancelButton = btnGroup.add("button", undefined, "Cancel");
var okButton = btnGroup.add("button", undefined, "OK");
// Folder selection logic
selectFolderButton.onClick = function () {
var selectedFolder = Folder.selectDialog("Select the source folder.");
if (selectedFolder) {
folderPathText.text = truncatePath(selectedFolder.fsName);
settings.folderPath = selectedFolder.fsName;
writeSettings(settings);
}
};
// Cancel and OK button logic
okButton.onClick = function () {
// Validate and save quantity
var quantity = parseInt(quantityInput.text, 10);
settings.quantity = isNaN(quantity) || quantity <= 0 ? 1 : quantity;
settings.reverseOrder = reverseOrderCheckbox.value;
settings.setFirstFileActive = setFirstFileActiveCheckbox.value;
writeSettings(settings);
dialog.close(1);
};
cancelButton.onClick = function () {
dialog.close(0);
};
return dialog.show() === 1;
}
// Truncate long paths for display
function truncatePath(path) {
var maxLength = 50;
if (path.length <= maxLength) return path;
var half = Math.floor(maxLength / 2) - 1;
return path.slice(0, half) + "..." + path.slice(-half);
}
// Settings functions
function readSettings() {
if (settingsFile.exists) {
settingsFile.open("r");
var settings = settingsFile.read();
settingsFile.close();
try {
return JSON.parse(settings);
} catch (e) {
return getDefaultSettings();
}
}
return getDefaultSettings();
}
function writeSettings(settings) {
settingsFile.open("w");
settingsFile.write(JSON.stringify(settings, null, 4));
settingsFile.close();
}
function getDefaultSettings() {
return {
index: 0,
folderPath: "",
quantity: 1,
reverseOrder: false,
setFirstFileActive: false
};
}
// Main logic to open the next set of files
function openNextFiles() {
var settings = readSettings();
var sourceFolder = settings.folderPath ? Folder(settings.folderPath) : null;
var lastIndex = settings.index;
// Check if we need to prompt for settings or reset index
if (!sourceFolder || !sourceFolder.exists || lastIndex < 0) {
if (!showMainDialog()) return;
settings = readSettings();
sourceFolder = settings.folderPath ? Folder(settings.folderPath) : null;
if (!sourceFolder || !sourceFolder.exists) return;
settings.index = 0;
writeSettings(settings);
lastIndex = 0;
}
// Collect valid image files
var files = sourceFolder.getFiles(function (file) {
return file instanceof File && file.name.match(/\.(psd|psb|tif|tiff|jpg|jpeg|png|webp)$/i);
});
if (files.length === 0) {
alert("No valid image files found in the selected folder.");
settings.folderPath = "";
writeSettings(settings);
return;
}
// Apply sorting and file limit based on settings
var quantity = settings.quantity;
var reverseOrder = settings.reverseOrder;
var setFirstFileActive = settings.setFirstFileActive;
if (reverseOrder) files.reverse();
var endIndex = Math.min(lastIndex + quantity, files.length);
var firstFileOpened = null;
// Open files in the specified range
for (var i = lastIndex; i < endIndex; i++) {
app.open(files[i]);
if (i === lastIndex && setFirstFileActive) {
firstFileOpened = app.activeDocument;
}
}
// Set the first file opened as active, if needed
if (firstFileOpened && setFirstFileActive) {
app.activeDocument = app.documents[0];
}
// Update index and save settings
settings.index = endIndex >= files.length ? -1 : endIndex;
writeSettings(settings);
// Alert if all files are opened
if (endIndex >= files.length) {
alert("All files in the folder have been opened. You'll be prompted to select a new folder next time.");
}
}
https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html