Copy link to clipboard
Copied
Hi all
I need a script that can be run from a batch action that copies the name of the individual file and pastes it into the title field in file info.
Anyone have one?
Thanks
Dave Smith
Hi Stephen
This is what ChatGPT finally came up with. I deleted my copyright info in case someone else want to use it.
Your thoughts?
#target photoshop
function copyFileNameToTitle() {
if (app.documents.length > 0) {
var doc = app.activeDocument;
var fileName = doc.name.replace(/\.[^\.]+$/, ''); // Get the file name without extension
try {
// Ensure the XMP library is available
if (ExternalObject.AdobeXMPScript == undefined) {
ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
}
// Get
...Your thoughts?
By @dcsimages
I haven't tested it, however, I can see that it is also adding a copyright flag and a copyright text line, which you didn't previously mention so the scripts I posted don't include this.
You could try to graft those extra bits of code into the scripts I posted to directly process metadata. Let me know if you hit any roadblocks.
I would not open each JPEG into Photoshop to update metadata, whether it was for 9 or 91,000 images, it's too slow and contributes to
...Copy link to clipboard
Copied
What file formats are being processed? Adobe Bridge would be a better place to do this, especially if the files are JPEG.
Photoshop can also update metadata without having to open the file.
Do you really need to do this on an open file? Is the batch action performing other steps, or only the metadata?
Copy link to clipboard
Copied
Hi Stephen
They are jpeg files. I have about 91000 files to process.
While I was waiting for an answer, I tried Chat GPT and after 5 iterations correcting errors, by telling it the error message, it was able to come up with a script that I can run by using an action and automate>batch.
What's the process using bridge and is the info written into the actual file and not a separate XML file?
Copy link to clipboard
Copied
JPEG files need to be decompressed and recompressed, which degrades image quality when opening into Photoshop and resaving from Photoshop.
Both Bridge and Photoshop can "inject" the metadata directly into the file without decompressing/recompressing the image data. Apart from quality, it is much faster to update metadata than to work with image data, especially if you have 91,000 files!
Here is an old Bridge script that should still work with later versions:
// Filename to metadata title.jsx
// https://forums.adobe.com/message/3596812
#target bridge
if( BridgeTalk.appName == "bridge" ) {
FT = MenuElement.create("command", "Add FileName to Description", "at the end of Tools");
}
FT.onSelect = function () {
var thumbs = app.document.selections;
if(!thumbs.length) return;
if (ExternalObject.AdobeXMPScript == undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
for(var a in thumbs){
var selectedFile = thumbs[a].spec;
var FileName = decodeURI(selectedFile.name).replace(/\.[^\.]+$/, '')
var myXmpFile = new XMPFile( selectedFile.fsName, XMPConst.UNKNOWN, XMPConst.OPEN_FOR_UPDATE);
var myXmp = myXmpFile.getXMP();
var Desc=[];
var count = myXmp.countArrayItems(XMPConst.NS_DC, "description");
for(var i = 1;i <= count;i++){
Desc.push(myXmp.getArrayItem(XMPConst.NS_DC, "description", i));
}
Desc=Desc.toString() + " " + FileName;
myXmp.deleteProperty(XMPConst.NS_DC, "description");
myXmp.appendArrayItem(XMPConst.NS_DC, "description", Desc, 0, XMPConst.ALIAS_TO_ALT_TEXT);
myXmp.setQualifier(XMPConst.NS_DC, "description[1]", "http://www.w3.org/XML/1998/namespace", "lang", "x-default");
if (myXmpFile.canPutXMP(myXmp)) {
myXmpFile.putXMP(myXmp);
myXmpFile.closeFile(XMPConst.CLOSE_UPDATE_SAFELY);
}
}
}
If you wish to keep the filename extension of JPG/JPEG, then remove the following:
.replace(/\.[^\.]+$/, '')
https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html
Copy link to clipboard
Copied
This script adds the filename to both the Title and Description metadata, it is easy enough to remove the Description bits if needed:
Copy link to clipboard
Copied
Another Bridge script:
/**
* @@@BUILDINFO@@@ FilenametoTitle.jsx !Version! Tue Nov 26 2019 09:07:36 GMT-0500
*/
/*
Utility Pack Scripts created by David M. Converse ©2018-19
Writes filename to Title metadata field.
/* Modified 30 March 2020 by Stephen Marsh to retain original filename in full */
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#target bridge
if (BridgeTalk.appName == 'bridge') {
try {
var FilenametoTitle = new Object; //id object for this script
#include "prefsReader.jsxinc" //shared prefs read code
//create menu
if (useMenu == true) { //use Tools submenu
if (MenuElement.find('utilPack') == null) { //submenu not yet created
MenuElement.create('menu', 'Utility Script Pack', 'at the end of Tools', 'utilPack');
}
var ftCmd = MenuElement.create('command', 'Filename to Title', 'at the end of utilPack');
}
else { //do not use submenu
var ftCmd = MenuElement.create('command', 'Filename to Title', 'at the end of Tools');
}
if (useCMenu == true) { //use contextual submenu
if (MenuElement.find('cutilPack') == null) {
MenuElement.create('menu', 'Utility Script Pack', 'after Thumbnail/Open', 'cutilPack');
}
var ftContCmd = MenuElement.create('command', 'Filename to Title', 'at the end of cutilPack'); //add to Contextual menu
}
else { //do not use contextual submenu
var ftContCmd = MenuElement.create('command', 'Filename to Title', 'after Thumbnail/Open', this.menuID); //add to Contextual menu
}
}
catch (e) {
//alert(e + e.line);
}
}
ftCmd.onSelect = function () {
ftAddFilenameToTitle();
}
ftContCmd.onSelect = function () {
ftAddFilenameToTitle();
}
function ftAddFilenameToTitle() {
try {
var ftThumbs = app.document.selections; //get selected thumbnails
if (!ftThumbs.length) return; //nothing selected
if (ExternalObject.AdobeXMPScript == undefined) ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
for (var a in ftThumbs) { //loop through thumbs
var ftTitle = ftThumbs[a].name; //get filename
//remove filename after last dash character
//to retain filename after dash, comment out lines 69-73
//ftTitle = ftTitle.split('-');
//if(ftTitle.length > 1){
// ftTitle.length--;
// }
//ftTitle = ftTitle.join('-');
//remove filename after last period character
//ftTitle = ftTitle.split('.');
//if(ftTitle.length > 1){
// ftTitle.length--;
// }
//ftTitle = ftTitle.join('.');
var ftMeta = ftThumbs[a].synchronousMetadata;
var ftXMP = new XMPMeta(ftMeta.serialize());
ftXMP.deleteProperty(XMPConst.NS_DC, 'title'); //delete old title
ftXMP.appendArrayItem(XMPConst.NS_DC, 'title', ftTitle, 0, XMPConst.ALIAS_TO_ALT_TEXT); //write new title
ftXMP.setQualifier(XMPConst.NS_DC, 'title[1]', 'http://www.w3.org/XML/1998/namespace', 'lang', 'x-default');
var ftUpdatedPacket = ftXMP.serialize(XMPConst.SERIALIZE_OMIT_PACKET_WRAPPER | XMPConst.SERIALIZE_USE_COMPACT_FORMAT);
ftThumbs[a].metadata = new Metadata(ftUpdatedPacket); //write to file
}
}
catch (e) {
//alert(e + e.line);
}
}
Copy link to clipboard
Copied
Here is a Photoshop script that "injects" the filename as title metadata into all files at the root level of the selected folder, without having to process the image data:
#target photoshop
app.activeDocument.info.title = app.activeDocument.name.replace(/\.[^\.]+$/, '');
Copy link to clipboard
Copied
Hi Stephen
This is what ChatGPT finally came up with. I deleted my copyright info in case someone else want to use it.
Your thoughts?
#target photoshop
function copyFileNameToTitle() {
if (app.documents.length > 0) {
var doc = app.activeDocument;
var fileName = doc.name.replace(/\.[^\.]+$/, ''); // Get the file name without extension
try {
// Ensure the XMP library is available
if (ExternalObject.AdobeXMPScript == undefined) {
ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
}
// Get the current XMP metadata
var xmp = new XMPMeta(doc.xmpMetadata.rawData);
// Remove existing title if any
xmp.deleteProperty(XMPConst.NS_DC, "title");
// Add new title as an array
xmp.appendArrayItem(XMPConst.NS_DC, "title", fileName, 0, XMPConst.ARRAY_IS_ORDERED);
// Set Copyright Status to "Copyrighted"
xmp.setProperty(XMPConst.NS_XMP_RIGHTS, "Marked", "True");
// Add Copyright description
xmp.setProperty(XMPConst.NS_DC, "rights", "Copyrighted by XXXXXXX ");
// Serialize the XMP data back to the document
doc.xmpMetadata.rawData = xmp.serialize(XMPConst.SERIALIZE_USE_COMPACT_FORMAT);
} catch (e) {
// Handle error
}
}
}
// Run the function
copyFileNameToTitle();
Copy link to clipboard
Copied
Your thoughts?
By @dcsimages
I haven't tested it, however, I can see that it is also adding a copyright flag and a copyright text line, which you didn't previously mention so the scripts I posted don't include this.
You could try to graft those extra bits of code into the scripts I posted to directly process metadata. Let me know if you hit any roadblocks.
I would not open each JPEG into Photoshop to update metadata, whether it was for 9 or 91,000 images, it's too slow and contributes to minor quality loss. Directly processing the metadata would be my best advice.
Yet another option is to use ExifTool to update the metadata, this would be my tool of choice for 91,000 images as it is CLI based (Windows OS would use double quotes " rather than ' single quotes as used on the Mac):
exiftool -overwrite_original_in_place '-title<${filename;s/\.[^.]*$//}' 'system path to top-level root folder or file'
or
exiftool -overwrite_original_in_place '-title<${filename;s/\.[^.]*$//}' -XMP-xmpRights:Marked=True -Photoshop:CopyrightFlag=True -XMP-dc:Rights='Copyrighted by XXXXXXX' -IFD0:Copyright='Copyrighted by XXXXXXX' -IPTC:CopyrightNotice='Copyrighted by XXXXXXX' 'system path to top-level root folder or file'
Here's another Bridge script, where I have added the copyright flag and string:
// https://imagesimple.wordpress.com/2011/08/24/cs5-filename-to-title-script/
#target bridge
if (BridgeTalk.appName == "bridge") {
FT = MenuElement.create("command", "TEST - Add FileName to Title", "at the end of Tools");
}
FT.onSelect = function () {
AddFilenameToTitle();
}
function AddFilenameToTitle() {
var thumbs = app.document.selections;
if (!thumbs.length) return;
if (ExternalObject.AdobeXMPScript == undefined) ExternalObject.AdobeXMPScript = new
ExternalObject("lib:AdobeXMPScript");
for (var a in thumbs) {
var selectedFile = thumbs[a].spec;
var Title = decodeURI(selectedFile.name).replace(/\.[^\.]+$/, '');
var myXmpFile = new XMPFile(selectedFile.fsName, XMPConst.UNKNOWN,
XMPConst.OPEN_FOR_UPDATE);
var myXmp = myXmpFile.getXMP();
myXmp.deleteProperty(XMPConst.NS_DC, "title");
myXmp.appendArrayItem(XMPConst.NS_DC, "title", Title, 0,
XMPConst.ALIAS_TO_ALT_TEXT);
myXmp.setQualifier(XMPConst.NS_DC, "title[1]",
"http://www.w3.org/XML/1998/namespace", "lang", "x-default");
myXmp.setProperty(XMPConst.NS_XMP_RIGHTS, "Marked", "True");
myXmp.setProperty(XMPConst.NS_DC, "rights", "Copyrighted by XXXXXXX ");
if (myXmpFile.canPutXMP(myXmp)) {
myXmpFile.putXMP(myXmp);
myXmpFile.closeFile(XMPConst.CLOSE_UPDATE_SAFELY);
}
}
}
Copy link to clipboard
Copied
I ended up using exiftools.
Thanks.
Copy link to clipboard
Copied
Hi Stephen
Would it be possible to add to this code a line to also write the file name to the author title at the same time?
Having some issues with the site I'm uploading to consistantly picking up the document title field and this was a suggestion from a fellow user who uses the author title field instead.
exiftool -overwrite_original_in_place '-title<${filename;s/\.[^.]*$//}' 'system path to top-level root folder or file'
Copy link to clipboard
Copied
My previous example assumed that metadata entries were empty, in this new example, I explicitly removed any metadata in the target fields before writing to them. Additionally, I am writing to both the XMP and legacy IPTC fields for backwards/wider compatibility. Perhaps if you write to the XMP-dc:Title and IPTC:ObjectName you may not even need to use the additional XMP-photoshop:AuthorsPosition and IPTC:By-lineTitle as suggested by the other user.
exiftool -overwrite_original_in_place -XMP-dc:Title= -XMP-photoshop:AuthorsPosition= -IPTC:By-lineTitle= -IPTC:ObjectName= '-XMP-dc:Title<${filename;s/\.[^.]*$//}' '-XMP-photoshop:AuthorsPosition<${filename;s/\.[^.]*$//}' '-IPTC:By-lineTitle<${filename;s/\.[^.]*$//}' '-IPTC:ObjectName<${filename;s/\.[^.]*$//}' 'system path to top-level root folder or file'
A variation on the above is to first write to the title, and then copy the title to the other fields. This may run a little slower, so you may wish to test a small batch to see which will run faster:
exiftool -XMP-dc:Title= -XMP-photoshop:AuthorsPosition= -IPTC:By-lineTitle= -IPTC:ObjectName= '-XMP-dc:Title<${filename;s/\.[^.]*$//}' -execute '-XMP-photoshop:AuthorsPosition<${XMP-dc:Title}' '-IPTC:By-lineTitle<${XMP-dc:Title}' '-IPTC:ObjectName<${XMP-dc:Title}' -common_args -overwrite_original_in_place 'system path to top-level root folder or file'
(Windows OS would use double quotes " rather than ' single quotes as used on the Mac)