Copy link to clipboard
Copied
I have a folder in Windows structured like this:
Folder1:
- Image1
- Image2
Folder2:
- Image2.1
- Image2.2
[...]
I want to import this folder to Photoshop and keep the exact same folder structure, but in groups. Is this possible without doing it manually?
A colleague helped me out by making a script. Case closed.
Copy link to clipboard
Copied
I’m not sure in what sense you want to import a folder to Photoshop. As I see it, you can edit images wherever they are and save them where you want. But that’s not importing a folder.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Copy link to clipboard
Copied
A colleague helped me out by making a script. Case closed.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Here's the script! Disclaimer from my colleague who wrote it: "It might not be the best way to handle it :)"
But it did the trick for me at least.
// ============================================================================
// Installation:
// 1. Place script in 'C:\Program Files\Adobe\Adobe Photoshop CS#\Presets\Scripts\'
// 2. Restart Photoshop
// 3. Choose File > Scripts > scriptname
// ============================================================================
// enable double-clicking from Mac Finder or Windows Explorer
#target photoshop
// bring application forward for double-click events
app.bringToFront();
///////////////////////////////////////////////////////////////////////////////
// main - main function
///////////////////////////////////////////////////////////////////////////////
function main() {
// user settings
var prefs = new Object();
prefs.sourceFolder = '~'; // default browse location (default: '~')
prefs.removeFileExtensions = true; // remove filename extensions for imported layers (default: true)
prefs.savePrompt = false; // display save prompt after import is complete (default: false)
prefs.closeAfterSave = false; // close import document after saving (default: false)
if (!documents.length){
alert("No open document to import into!");
return;
}
// prompt for source folder
var sourceFolder = Folder.selectDialog('Please select the folder to be imported:', Folder(prefs.sourceFolder));
// ensure the source folder is valid
if (!sourceFolder) {
return;
}
else if (!sourceFolder.exists) {
alert('Source folder not found.', 'Script Stopped', true);
return;
}
// add source folder to user settings
prefs.sourceFolder = sourceFolder;
var got_files = false;
// get a list of folders
var folderArray = getFolders(prefs.sourceFolder);
var len = folderArray.length;
// loop through folders
app.togglePalettes();
for (var i = 0; i < len; i++) {
// get a list of files
var fileArray = getFiles(folderArray[i]);
// if files were found, proceed with import
if (fileArray.length) {
var layer = importFolder(folderArray[i]);
importFilesInLayer(fileArray, layer, prefs);
got_files = true;
}
}
app.togglePalettes();
// if no files found , diplay message
if (!got_files) {
alert("The selected folder doesn't contain any recognized images.", 'No Files Found', false);
}
}
///////////////////////////////////////////////////////////////////////////////
// getFiles - get all files within the specified source
///////////////////////////////////////////////////////////////////////////////
function getFiles(sourceFolder) {
// declare local variables
var fileArray = new Array();
var extRE = /\.(?:png|gif|jpg|bmp|tif|psd)$/i;
// get all files in source folder
var docs = sourceFolder.getFiles();
var len = docs.length;
for (var i = 0; i < len; i++) {
var doc = docs[i];
// only match files (not folders)
if (doc instanceof File) {
// store all recognized files into an array
var docName = doc.name;
if (docName.match(extRE)) {
fileArray.push(doc);
}
}
}
// return file array
return fileArray;
}
function getFolders(sourceFolder) {
// declare local variables
var folderArray = new Array();
// get all items in source folder
var items = sourceFolder.getFiles();
var len = items.length;
for (var i = 0; i < len; i++) {
var item = items[i];
// only match files (not folders)
if (item instanceof Folder) {
// store all recognized files into an array
folderArray.push(item);
}
}
// return folder array
return folderArray;
}
///////////////////////////////////////////////////////////////////////////////
// importFolderAsLayers - imports a folder of images as named layers
///////////////////////////////////////////////////////////////////////////////
function importFolder(folderName){
// get folder name
var path = folderName.toString();
var lastIndex = path.lastIndexOf("/");
var folder = path.slice(lastIndex + 1);
var newLayer = app.activeDocument.layerSets.add();
newLayer.name = folder
return newLayer
}
function importFilesInLayer(fileArray, layer, prefs) {
// loop through all files in the source folder
for (var i = fileArray.length -1; i >= 0; i--) {
// open document
var curr_file = app.open(fileArray[i]);
// get file name
var name = curr_file.name;
name = name.replace(/(?:\.[^.]*$|$)/, '');
// copy file and paste into current file
curr_file.selection.selectAll();
curr_file.selection.copy();
curr_file.close(SaveOptions.DONOTSAVECHANGES);
curr_layer = app.activeDocument.paste();
// rename
curr_layer.name = name
}
// reveal and trim to fit all layers
app.activeDocument.revealAll();
}
///////////////////////////////////////////////////////////////////////////////
// isCorrectVersion - check for Adobe Photoshop CS2 (v9) or higher
///////////////////////////////////////////////////////////////////////////////
function isCorrectVersion() {
if (parseInt(version, 10) >= 9) {
return true;
}
else {
alert('This script requires Adobe Photoshop CS2 or higher.', 'Wrong Version', false);
return false;
}
}
///////////////////////////////////////////////////////////////////////////////
// showError - display error message if something goes wrong
///////////////////////////////////////////////////////////////////////////////
function showError(err) {
if (confirm('An unknown error has occurred.\n' +
'Would you like to see more information?', true, 'Unknown Error')) {
alert(err + ': on line ' + err.line, 'Script Error', true);
}
}
// test initial conditions prior to running main function
if (isCorrectVersion()) {
// remember ruler units; switch to pixels
var originalRulerUnits = preferences.rulerUnits;
preferences.rulerUnits = Units.PIXELS;
try {
main();
}
catch(e) {
// don't report error on user cancel
if (e.number != 8007) {
showError(e);
}
}
// restore original ruler unit
preferences.rulerUnits = originalRulerUnits;
}
Copy link to clipboard
Copied
Since all the google results points to pages containing this code,
I'm posting here an updated version that:
- Check both folders and subfolders.
- Uses Place from Action Commands, instead of doing repeated ctr+c / ctrl+v commands
- Condenses all of the actions in a single History task.
var obj = {};
var extRE = /\.(?:png|gif|jpg|bmp|tif|psd)$/i;
cTID = function(s) {
return app.charIDToTypeID(s);
};
sTID = function(s) {
return app.stringIDToTypeID(s);
};
function listFolders(folder, obj) {
var files = folder.getFiles();
for (var i = 0; i < files.length; i++) {
var file = files[i];
if (file instanceof Folder) {
obj[file.name] = {};
listFolders(file, obj[file.name]);
} else {
obj[file.name] = file;
}
}
obj = sortObject(obj);
}
function sortObject(obj) {
var sorted = {};
var keys = [];
for (var key in obj) {
keys.push(key);
}
keys.sort(function(a, b) {
var intA = parseInt(a.replace(/\D/g, ""));
var intB = parseInt(b.replace(/\D/g, ""));
if (isNaN(intA) || isNaN(intB)) {
return a.localeCompare(b);
} else {
return intA - intB;
}
});
for (var i = 0; i < keys.length; i++) {
if (obj[keys[i]] instanceof Object) {
sorted[keys[i]] = sortObject(obj[keys[i]]);
} else {
sorted[keys[i]] = obj[keys[i]];
}
}
return sorted;
}
function createLayerSets(obj, parent) {
for (var key in obj) {
if (obj[key] instanceof Object) {
if (key.match(extRE)) {
placeFile(obj[key], parent.itemIndex -1);
} else {
var group = parent.layerSets.add();
group.name = key;
createLayerSets(obj[key], group);
}
} else {
var layer = parent.artLayers.add();
layer.name = key;
}
}
}
function main(){
var folder = Folder.selectDialog("Select a folder to list");
if (folder != null) {
listFolders(folder, obj);
createLayerSets(obj, app.activeDocument);
}
}
app.activeDocument.suspendHistory ("Import Folders and Sub Folders", "main()");
function placeFile(filePath, index) {
(function(enabled, withDialog) {
if (void 0 == enabled || enabled) {
enabled = withDialog ? DialogModes.ALL : DialogModes.NO;
withDialog = new ActionDescriptor();
withDialog.putInteger(cTID("Idnt"), 19);
withDialog.putPath(cTID("null"), new File(filePath));
withDialog.putEnumerated(cTID("FTcs"), cTID("QCSt"), sTID("QCSAverage"));
var desc2 = new ActionDescriptor();
desc2.putUnitDouble(cTID("Hrzn"), cTID("#Pxl"), 0);
desc2.putUnitDouble(cTID("Vrtc"), cTID("#Pxl"), 0);
withDialog.putObject(cTID("Ofst"), cTID("Ofst"), desc2);
executeAction(cTID("Plc "), withDialog, enabled);
}
})();
(function(enabled, withDialog) {
if (void 0 == enabled || enabled) {
enabled = withDialog ? DialogModes.ALL : DialogModes.NO;
withDialog = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putEnumerated(cTID("Lyr "), cTID("Ordn"), cTID("Trgt"));
withDialog.putReference(cTID("null"), ref1);
ref1 = new ActionReference();
ref1.putIndex(cTID("Lyr "), index);
withDialog.putReference(cTID("T "), ref1);
withDialog.putBoolean(cTID("Adjs"), !1);
withDialog.putInteger(cTID("Vrsn"), 5);
ref1 = new ActionList();
ref1.putInteger(428);
withDialog.putList(cTID("LyrI"), ref1);
executeAction(cTID("move"), withDialog, enabled);
}
})();
}
It was a lot of work, but it turned out better than anything else I have tried.
Copy link to clipboard
Copied
@mauroj62447795 – thank you for sharing and joining in the community spirit!
Copy link to clipboard
Copied
I'll just add this little update to the previous code: if you are getting the dreaded "%20" instead of a space on all of your layers then this is the code from above with a little gem that takes care of that 🙂
var obj = {};
var extRE = /\.(?:png|gif|jpg|bmp|tif|psd)$/i;
cTID = function(s) {
return app.charIDToTypeID(s);
};
sTID = function(s) {
return app.stringIDToTypeID(s);
};
function listFolders(folder, obj) {
var files = folder.getFiles();
for (var i = 0; i < files.length; i++) {
var file = files[i];
if (file instanceof Folder) {
var folderName = decodeURIComponent(file.name);
obj[folderName] = {};
listFolders(file, obj[folderName]);
} else {
var fileName = decodeURIComponent(file.name);
obj[fileName] = file;
}
}
obj = sortObject(obj);
}
function sortObject(obj) {
var sorted = {};
var keys = [];
for (var key in obj) {
keys.push(key);
}
keys.sort(function(a, b) {
var intA = parseInt(a.replace(/\D/g, ""));
var intB = parseInt(b.replace(/\D/g, ""));
if (isNaN(intA) || isNaN(intB)) {
return a.localeCompare(b);
} else {
return intA - intB;
}
});
for (var i = 0; i < keys.length; i++) {
if (obj[keys[i]] instanceof Object) {
sorted[keys[i]] = sortObject(obj[keys[i]]);
} else {
sorted[keys[i]] = obj[keys[i]];
}
}
return sorted;
}
function createLayerSets(obj, parent) {
for (var key in obj) {
if (obj[key] instanceof Object) {
if (key.match(extRE)) {
placeFile(obj[key], parent.itemIndex -1);
} else {
var group = parent.layerSets.add();
group.name = key;
createLayerSets(obj[key], group);
}
} else {
var layer = parent.artLayers.add();
layer.name = key;
}
}
}
function main(){
var folder = Folder.selectDialog("Select a folder to list");
if (folder != null) {
listFolders(folder, obj);
createLayerSets(obj, app.activeDocument);
}
}
app.activeDocument.suspendHistory ("Import Folders and Sub Folders", "main()");
function placeFile(filePath, index) {
(function(enabled, withDialog) {
if (void 0 == enabled || enabled) {
enabled = withDialog ? DialogModes.ALL : DialogModes.NO;
withDialog = new ActionDescriptor();
withDialog.putInteger(cTID("Idnt"), 19);
withDialog.putPath(cTID("null"), new File(filePath));
withDialog.putEnumerated(cTID("FTcs"), cTID("QCSt"), sTID("QCSAverage"));
var desc2 = new ActionDescriptor();
desc2.putUnitDouble(cTID("Hrzn"), cTID("#Pxl"), 0);
desc2.putUnitDouble(cTID("Vrtc"), cTID("#Pxl"), 0);
withDialog.putObject(cTID("Ofst"), cTID("Ofst"), desc2);
executeAction(cTID("Plc "), withDialog, enabled);
}
})();
(function(enabled, withDialog) {
if (void 0 == enabled || enabled) {
enabled = withDialog ? DialogModes.ALL : DialogModes.NO;
withDialog = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putEnumerated(cTID("Lyr "), cTID("Ordn"), cTID("Trgt"));
withDialog.putReference(cTID("null"), ref1);
ref1 = new ActionReference();
ref1.putIndex(cTID("Lyr "), index);
withDialog.putReference(cTID("T "), ref1);
withDialog.putBoolean(cTID("Adjs"), !1);
withDialog.putInteger(cTID("Vrsn"), 5);
ref1 = new ActionList();
ref1.putInteger(428);
withDialog.putList(cTID("LyrI"), ref1);
executeAction(cTID("move"), withDialog, enabled);
}
})();
}