Skip to main content
Participant
June 6, 2019
Answered

Bridge script to write filename to Description, Credit Line, andTitle lines

  • June 6, 2019
  • 5 replies
  • 10711 views

Hello! I'm in search of a Bridge script that will write a filename (without file extension) to the description line, title line, and Credit line (without overwriting!) in my IPTC metadata. I've looked around and haven't found something already written that does this and I don't quite have enough skills to write it myself or adapt something that exists already. Any leads or suggestions? Thanks!!

This topic has been closed for replies.
Correct answer Stephen Marsh

Using ExifTool, the command line code to copy the filename to the description metadata tag without extension would be:

 

 

exiftool '-description<${filename;s/\.[^\.]+$//}' -r 'path to file or folder here'

 

 

This command line code example is from the Mac, on Windows simply change the single straight quote/foot mark ' to straight double quote/inch marks " with the correct platform-specific path to the file or top-level folder. It uses a recursive argument to process all files in all folders under the top-level folder. Further arguments can be added to only process certain file types or to ignore specific directories under the top-level directory path. This code duplicates and renames the original file for safety, and one can add the -overwrite_original argument to turn off this behaviour.

 

5 replies

Stephen Marsh
Community Expert
Community Expert
November 16, 2023

An addition raised in another topic in the Photoshop forum... The following script can be used to find/replace/remove title data (I believe that this script was most likely written by Paul Riggot):

 

To clear the title you can use a regular expression find (replacing with nothing):

 

.+

 

 

#target bridge
if (BridgeTalk.appName == "bridge") {
    ReplaceTitle = new MenuElement("command", "Find and Replace in Title", "at the end of tools");
}
ReplaceTitle.onSelect = function () {
    var win = new Window('dialog', 'Find & Replace in Title');
    g = win.graphics;
    var myBrush = g.newBrush(g.BrushType.THEME_COLOR, "appDialogBackground");
    g.backgroundColor = myBrush;
    win.orientation = 'column';
    win.p1 = win.add("panel", undefined, undefined, { borderStyle: "black" });
    win.p1.preferredSize = [380, 100];
    win.g1 = win.p1.add('group');
    win.g1.orientation = "row";
    win.title = win.g1.add('statictext', undefined, 'Title Editor');
    win.title.alignment = "fill";
    var g = win.title.graphics;
    g.font = ScriptUI.newFont("Arial", "BOLD", 22);
    win.p6 = win.p1.add("panel", undefined, undefined, { borderStyle: "black" }); //Replace
    win.p6.preferredSize = [380, 100];
    win.g600 = win.p6.add('group');
    win.g600.orientation = "row";
    win.g600.alignment = 'fill';
    win.g600.st1 = win.g600.add('statictext', undefined, 'Replace');
    win.g600.st1.preferredSize = [75, 20];
    win.g600.et1 = win.g600.add('edittext');
    win.g600.et1.preferredSize = [200, 20];
    win.g610 = win.p6.add('group');
    win.g610.orientation = "row";
    win.g610.alignment = 'fill';
    win.g610.st1 = win.g610.add('statictext', undefined, 'With');
    win.g610.st1.helpTip = "Leave this field blank if you want to remove the characters";
    win.g610.st1.preferredSize = [75, 20];
    win.g610.et1 = win.g610.add('edittext');
    win.g610.et1.preferredSize = [200, 20];
    win.g620 = win.p6.add('group');
    win.g620.orientation = "row";
    win.g620.alignment = 'fill';
    win.g620.cb1 = win.g620.add('checkbox', undefined, 'Global');
    win.g620.cb1.helpTip = "Replace all occurrences of";
    win.g620.cb2 = win.g620.add('checkbox', undefined, 'Case Insensitive');
    win.g620.cb2.value = true;
    win.g1000 = win.p1.add('group');
    win.g1000.orientation = "row";
    win.g1000.alignment = 'center';
    win.g1000.bu1 = win.g1000.add('button', undefined, 'Process');
    win.g1000.bu1.preferredSize = [170, 30];
    win.g1000.bu2 = win.g1000.add('button', undefined, 'Cancel');
    win.g1000.bu2.preferredSize = [170, 30];
    win.g1000.bu1.onClick = function () {
        if (win.g600.et1.text == '') {
            alert("No replace value has been entered!");
            return;
        }
        win.close(0);
        var sels = app.document.selections;
        for (var a in sels) {
            var thumb = sels[a];
            md = thumb.synchronousMetadata;
            if (win.g620.cb1.value && !win.g620.cb2.value) var patt = new RegExp(win.g600.et1.text.toString(), "g");
            if (!win.g620.cb1.value && win.g620.cb2.value) var patt = new RegExp(win.g600.et1.text.toString(), "i");
            if (win.g620.cb1.value && win.g620.cb2.value) var patt = new RegExp(win.g600.et1.text.toString(), "gi");
            if (!win.g620.cb1.value && !win.g620.cb2.value) var patt = new RegExp(win.g600.et1.text.toString());
            md.namespace = "http://purl.org/dc/elements/1.1/";
            var Caption = md.title ? md.title[0] : "";
            if (Caption == "") continue;
            var result = patt.test(Caption.toString());
            if (result == true) {
                var newCaption = Caption.replace(patt, win.g610.et1.text.toString());
                setTitle(sels[a].spec, newCaption);
            }
        }
    }
    win.show();
    function setTitle(file, Caption) {
        if (!ExternalObject.AdobeXMPScript) ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
        var xmpf = new XMPFile(File(file).fsName, XMPConst.UNKNOWN, XMPConst.OPEN_FOR_UPDATE);
        var xmp = xmpf.getXMP();
        xmp.deleteProperty(XMPConst.NS_DC, "title");
        xmp.setLocalizedText(XMPConst.NS_DC, "title", null, "x-default", Caption);
        if (xmpf.canPutXMP(xmp)) {
            xmpf.putXMP(xmp);
        }
        xmpf.closeFile(XMPConst.CLOSE_UPDATE_SAFELY);
    }
};

 

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

_wckdTall_
Inspiring
November 29, 2023

Thanks again for this. I think the issue is that the persistent data occurs outside of metadata. I did get it to replace the title, but it doesn't replace the additional title fields in the file. Is there a way to access these via bridge? I've been poking around with John Wundes "The Document Object Model Explorer v.2 -- CS", but it stops reading the objects quickly. It wasn't intended for this, but does a pretty good job with InDesign and Photoshop. 

_wckdTall_
Inspiring
November 29, 2023

Still interested if there's a way to adjust info outside of headers within bridge. But in testing, I've found that the reason AEM was recognizing these extraneous titles, was because I was deleting XMP title field but not appending a blank one back and setting a qualifier.

        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");


Titles still incorrectly appear here(I think this is postscript/pdf?):

%!PS-Adobe-3.0 
%%Creator: Adobe Illustrator(R) 24.0
%%AI8_CreatorVersion: 28.0.0
%%For: (MY_USER_NAME) ()
%%Title: (Untitled-3)

And here, this is where AEM pulls from if it doesn't have a title field:

35 0 obj
<</CreationDate(D:20231128231255-05'00')/Creator(Adobe Illustrator 28.0 \(Macintosh\))/ModDate(D:20231128231256-05'00')/Producer(Adobe PDF library 17.00)/Title(THIS_IS_ANOTHER_TITLE)>>
endobj
xref


I have opened the AI files within text edit to find these additional titles, would love to know how to remove extraneous data like this, since at it contains user names etc. Not sure if it's related, but I saw exif tool does have a "For" field that read in the username.

Stephen Marsh
Community Expert
Community Expert
April 5, 2021

 

MarkLane1 

 

It turns out that I didn't have a script that writes the filename to both the Description and Title metadata fields.

 

I have adjusted an existing script for Description to also include the Title:

 

/* Original script modified by Stephen Marsh - 2021
https://community.adobe.com/t5/bridge/bridge-script-to-write-filename-to-description-credit-line-andtitle-lines/td-p/10489128
https://forums.adobe.com/thread/2009311 */

#target bridge

if (BridgeTalk.appName == "bridge") {
    FT = MenuElement.create("command", "Add Filename to Description and Title", "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 Title = [];
        var descCount = myXmp.countArrayItems(XMPConst.NS_DC, "description");
        var titleCount = myXmp.countArrayItems(XMPConst.NS_DC, "title");

        for (var i = 1; i <= descCount; i++) {
            Desc.push(myXmp.getArrayItem(XMPConst.NS_DC, "description", i));
        }

        for (var i = 1; i <= titleCount; i++) {
            Title.push(myXmp.getArrayItem(XMPConst.NS_DC, "title", i));
        }

        Desc = Desc.toString() + " " + FileName;
        Title = Desc;

        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");

        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");

        if (myXmpFile.canPutXMP(myXmp)) {
            myXmpFile.putXMP(myXmp);
            myXmpFile.closeFile(XMPConst.CLOSE_UPDATE_SAFELY);
        }
    }
}

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

 

 

Participating Frequently
April 5, 2021

I was searching for a way to do just this, and found the original Script by John Beardsworth works with changes to the meta line needed. But I was wondering, is there a way to have only part of the file name placed into each line, on mass?
eg. I have a filename structure of:  

ABCD 0123 ABCD AB-CD AB19 0123 AB19 AB19.jpg

so sections:

A B C D E F G H.jpg

Basicly a whole mix of alphanumerics some fixed length some not. All delimiters are spaces (but can be anything).

I was wondering if it was possible to write section A to, say, Comments. B to City, C to Source, D to Headline, etc....

So far I've been doing it long hand by renaming the files to only the relevant section Setting the metadata with johns script and reverting the filename, repeating for each section. I am using a dusted off copy of cs6 as i cant get these to run in CC.
I know there is a way to do this in ExifTool but I'm still learning the syntax and cant figure out the right commands, plus if im not around at least someone else can just hit a button in Bridge with out me explaining how to work Exiftool to them.

Any help would be greatly appreciated.

Stephen Marsh
Community Expert
Community Expert
April 5, 2021

I'm not following the pattern, however, once a consistent pattern is found it should be easy enough with a regular expression or another method...

 

Please colour code or bold the source:

 

ABCD 0123 ABCD AB-CD AB19 0123 AB19 AB19.jpg

 

So that I can see how you get:

 

A B C D E F G H.jpg

 

And it is usally best to supply more than one set of before after, say 3 to 6 examples just in case the pattern is not consistent.

Participating Frequently
June 11, 2020

Did you ever find a Bridge script to write filename to Description? I too am interested in finding a script like this for the newest version of Adobe Bridge. Can you share any resources?

Morgan Howarth

[Edit by moderator: I've taken out your public email, you probably do not want to share that with everyone]

 

Please PM me if you have information! Thank you.

Stephen Marsh
Community Expert
Community Expert
June 13, 2020

 

I posted the following code earlier in the topic thread, which adds the file name to the description field, removing the filename extension...

 

EDIT 11th April 2023: Code updated and tested with Bridge 2022 –

 

// https://forums.adobe.com/message/10061534#10061534
// https://forums.adobe.com/message/3595421#3595421
#target bridge
   if( BridgeTalk.appName == "bridge" ) {
fileToDesc = MenuElement.create("command", "TEST - Add FileName to Description", "at the end of Tools");
}
fileToDesc.onSelect  = function () {
var thumbs = app.document.selections;
if (ExternalObject.AdobeXMPScript == undefined)  ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
for(var a =0;a<thumbs.length;a++){
var selectedFile =  new Thumbnail(thumbs[a]);
app.synchronousMode = true;
var xmp = new XMPMeta(selectedFile.synchronousMetadata.serialize());
var Desc = getArrayItems(XMPConst.NS_DC, "description");
if(Desc != "") Desc+= ";";
xmp.deleteProperty(XMPConst.NS_DC, "description");
xmp.setLocalizedText( XMPConst.NS_DC, "description", null, "x-default", Desc +=  decodeURI(selectedFile.spec.name).replace(/\..+$/,""));
var newPacket = xmp.serialize(XMPConst.SERIALIZE_USE_COMPACT_FORMAT);
selectedFile.metadata = new Metadata(newPacket);
    }
ExternalObject.AdobeXMPScript.unload();
ExternalObject.AdobeXMPScript = undefined;
function getArrayItems(ns, prop){
var arrItem=[];
try{
var items = xmp.countArrayItems(ns, prop);
for(var i = 1;i <= items;i++){
arrItem.push(xmp.getArrayItem(ns, prop, i));
}
return arrItem.toString();
}catch(e){alert(e +" Line: "+ e.line);}
    }
};

 

 

 

Stephen Marsh
Community Expert
Stephen MarshCommunity ExpertCorrect answer
Community Expert
June 13, 2020

Using ExifTool, the command line code to copy the filename to the description metadata tag without extension would be:

 

 

exiftool '-description<${filename;s/\.[^\.]+$//}' -r 'path to file or folder here'

 

 

This command line code example is from the Mac, on Windows simply change the single straight quote/foot mark ' to straight double quote/inch marks " with the correct platform-specific path to the file or top-level folder. It uses a recursive argument to process all files in all folders under the top-level folder. Further arguments can be added to only process certain file types or to ignore specific directories under the top-level directory path. This code duplicates and renames the original file for safety, and one can add the -overwrite_original argument to turn off this behaviour.

 

Participating Frequently
May 17, 2020

It's hard to believe that in 2020 this feature is not a standard in Adobe - All photographers use META and for me the best program for writing it is ACDSee as this feature has existed for a decade, but I am looking at swapping to Adobe products but all these limitations with XMP over XML are putting me off switching over. It would be nice if we had a way of just selecting a Parent folder, then everything inside those folders get written too, this is possible in ACDSee but you have toi tag each folder which makes it a long winded process but wtill much better than this Bridge nonsense 😕😕

Stephen Marsh
Community Expert
Community Expert
June 7, 2019

I don't have one script that does all three... But I do have three separate scripts. I could possibly combine them with time/effort, but no promises as I'm new to scripting.

I did manage to hack an existing script to add the Filename to the Headline into the Credit:

// Bridge script to write filename to Description, Credit Line, andTitle lines

// https://forums.adobe.com/thread/656144 

// https://forums.adobe.com/message/9744916 

// https://forums.adobe.com/message/9745231 

#target bridge 

addNametoMeta = {}; 

addNametoMeta.execute = function(){ 

  var sels = app.document.selections; 

  for (var i = 0; i < sels.length; i++){ 

var md = sels.synchronousMetadata; 

    md.namespace = "http://ns.adobe.com/photoshop/1.0/"; 

    var Name = decodeURI(sels.name).replace(/\.[^\.]+$/g, ' '); //remove extension  

    md.Credit = md.Credit + Name; 

  } 

if (BridgeTalk.appName == "bridge"){ 

var menu = MenuElement.create( "command", "Add filename to Credit", "at the end of Tools"); 

  menu.onSelect = addNametoMeta.execute; 

}

Here is the code for Filename to Description:

// https://forums.adobe.com/message/10061534#10061534

// https://forums.adobe.com/message/3595421#3595421

#target bridge

   if( BridgeTalk.appName == "bridge" ) {

fileToDesc = MenuElement.create("command", "Add FileName to Description", "at the end of Tools");

}

fileToDesc.onSelect  = function () {

var thumbs = app.document.selections;

if (ExternalObject.AdobeXMPScript == undefined)  ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");

for(var a =0;a<thumbs.length;a++){

var selectedFile =  new Thumbnail(thumbs);

app.synchronousMode = true;

var xmp = new XMPMeta(selectedFile.synchronousMetadata.serialize());

var Desc = getArrayItems(XMPConst.NS_DC, "description");

if(Desc != "") Desc+= ";";

xmp.deleteProperty(XMPConst.NS_DC, "description");

xmp.setLocalizedText( XMPConst.NS_DC, "description", null, "x-default", Desc +=  decodeURI(selectedFile.spec.name).replace(/\..+$/,""));

var newPacket = xmp.serialize(XMPConst.SERIALIZE_USE_COMPACT_FORMAT);

selectedFile.metadata = new Metadata(newPacket);

    }

ExternalObject.AdobeXMPScript.unload();

ExternalObject.AdobeXMPScript = undefined;

function getArrayItems(ns, prop){

var arrItem=[];

try{

var items = xmp.countArrayItems(ns, prop);

for(var i = 1;i <= items;i++){

arrItem.push(xmp.getArrayItem(ns, prop, i));

}

return arrItem.toString();

}catch(e){alert(e +" Line: "+ e.line);}

    }

};

Here is the code for Filename to Title:

// https://imagesimple.wordpress.com/2011/08/24/cs5-filename-to-title-script/

#target bridge

   if( BridgeTalk.appName == "bridge" ) {

FT = MenuElement.create("command", "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.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");

        if (myXmpFile.canPutXMP(myXmp)) {

        myXmpFile.putXMP(myXmp);

         myXmpFile.closeFile(XMPConst.CLOSE_UPDATE_SAFELY);

         }

    }

}

After running all three scripts, I used ExifTool to confirm which metadata tags were written:

[IPTC]           ObjectName                    

[IPTC]           Credit                         

[IPTC]           Caption-Abstract               

[IFD0]           ImageDescription               

[XMP-dc]     Title                          

[XMP-dc]     Description                    

[XMP-photoshop]    Credit

And here is the result from Bridge's Metadata panel for a file titled "colour FILE-Test.psd":

Stephen Marsh
Community Expert
Community Expert
June 7, 2019

An equivalent ExifTool command line could be:

exiftool '-IPTC:ObjectName<${filename;s/\.[^.]*$//}' '-IPTC:Credit<${filename;s/\.[^.]*$//}' '-IPTC:Caption-Abstract<${filename;s/\.[^.]*$//}' '-IFD0:ImageDescription<${filename;s/\.[^.]*$//}' '-XMP-dc:Title<${filename;s/\.[^.]*$//}' '-XMP-dc:Description<${filename;s/\.[^.]*$//}' '-XMP-photoshop:Credit<${filename;s/\.[^.]*$//}' -r 'pathTOfileORfolder'