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

Find and Replace function for Bridge

Community Beginner ,
May 17, 2022 May 17, 2022

Copy link to clipboard

Copied

Hi there. I used to have this incredible Find and Replace function for Bridge. It meant I could strip out a given part of a caption in the description field and replace it. I used it to strip out credit information. It used to look like this. I recently had to wipe and reinstall my Mac and I have lost it. Does anyone know where I can get this and how to load it back into Bridge? Thank you!Screenshot 2022-05-17 at 12.12.15.pngScreenshot 2022-05-17 at 12.10.57.png

TOPICS
How to , Metadata

Views

495

Likes

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

correct answers 1 Correct answer

Community Expert , May 21, 2022 May 21, 2022
Looking at Paul Riggott's original Find Replace In Description script, I noticed that it runs this command when it loads: app.document.chooseMenuItem("PurgeCacheForSelected");
 
I'm guessing that there was a problem with metadata edits not always displaying and that purging the cache solved that. Ineed, I experienced the same blank Description as @mikejlkemp after running Find Replace In Description. I then manually purged the cache and the edited Description displayed.
 
Riggott's script used a sim
...

Likes

Translate

Translate
Community Expert ,
May 17, 2022 May 17, 2022

Copy link to clipboard

Copied

I think that script was created by Paul Riggott. You can find his scripts at https://github.com/Paul-Riggott/PS-Scripts 

The one you want is Find and Replace.jsx It looks like it has been updated from the version you have. it now allows you to edit metadata in many different fields (your version only changed Description/Caption).

Likes

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 ,
May 17, 2022 May 17, 2022

Copy link to clipboard

Copied

Thank you very much for that Greg, that hopefully will do it! Do you know how I input that script into Bridge to make it work? (apologies, I am no expert.) Thanks again, Mike

Likes

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 ,
May 17, 2022 May 17, 2022

Copy link to clipboard

Copied

No problem. Here's how you install it:

 

On Github, click the green Code button, then click Download ZIP

gregreser_0-1652814849017.png

 

Unzip this and look for the file Find and Replace.jsx

You will copy this file in the Bridge Startup Scripts folder. To find this folder:

In Bridge, go to Preferences > Startup Scripts > Reveal My Startup Scripts

gregreser_1-1652815163883.png

 

Copy Find and Replace.jsx in this folder.

Restart Bridge and confirm you want to load the script.

It should now appear in the Tools menu.

 

Let me know how it goes.

Likes

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 ,
May 18, 2022 May 18, 2022

Copy link to clipboard

Copied

Thanks Greg, very clearly explained! I just loaded it and tested, but it has stripped out the entire caption / description field. What I use this for is to take out photo credits from captions. But for some reason the entire caption is now gone. Any ideas?

Likes

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 ,
May 18, 2022 May 18, 2022

Copy link to clipboard

Copied

Oh, that's not good. I was able to reproduce the problem, but something weird is going on. When I restarted Bridge, the replacement description was there. This script is an old script, maybe the metadata writing function needs to be updated for newer versions of Bridge.

@Stephen_A_Marsh maybe your script would work better

Likes

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 ,
May 17, 2022 May 17, 2022

Copy link to clipboard

Copied

I'm not seeing the option for the IPTC Caption in there, unless my version is different:

 

find-replace.png

 

I do have a "Find & Replace in Title" script, that could be modified for Caption:

 

Title.png

 

In both cases, I updated the code for a "dark mode theme".

 

EDIT:

Found it, my one was called "Find & Replace in Description"!

Likes

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 ,
May 17, 2022 May 17, 2022

Copy link to clipboard

Copied

Yes, that is right. I think dc:description is the same as Caption.

Thanks for updating the panel colors. I foget which version of Bridge broke those, but older scripts usually need to be changed.

Likes

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 ,
May 18, 2022 May 18, 2022

Copy link to clipboard

Copied

Well @Stephen_A_Marsh a Find and Replace in Description would be very useful at this very moment! Yes, the one I got from Github stips the entire caption out. I need on mainly for the caprion / description field, which also gives the option to remove any ( ) brackets as the information I always have to remove is in brackets. I am using Version 12.0.2.252 of Bridge. Maybe you can be the one to save the day... Mike

Likes

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 ,
May 18, 2022 May 18, 2022

Copy link to clipboard

Copied

Sadly, as "luck" would have it, my MacBook battery has died and I can't even power up from the mains, looks like the battery is the "gatekeeper" so I'm out of action until I get this fixed, hopefully only a day or two downtime... 

 

P.S. try searching the forum, the code may be posted in an old topic.

Likes

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 ,
May 18, 2022 May 18, 2022

Copy link to clipboard

Copied

Sorry to hear that @Stephen_A_Marsh 

I dug through my old files and found the original code. I modified it slightly to improve the color (just eliminated the background color) which looks good on Windows. Let me know if it's okay for you. I also renamed it Description/Caption for clarity. It is working for me. Fingers crossed...

 

I can't up load a .jsx or .zip file here, so the code is below. You can copy and paste itno a text editor and save that as a .jsx file. Then copy the file to your Startup Scripts folder.  If that doesn't work, I can share my email on a private chat.

#target bridge 
if( BridgeTalk.appName == "bridge" ) { 
ReplaceDescription = new MenuElement("command", "Find and Replace Description/Caption", "at the end of tools");
}
ReplaceDescription.onSelect = function () { 
var win = new Window( 'dialog', 'Find & Replace' ); 
//g = win.graphics;
//var myBrush = g.newBrush(g.BrushType.SOLID_COLOR, [0.99, 0.99, 0.99, 1]);
//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,'Description/Caption Editor');
win.title.alignment="fill";
var g = win.title.graphics;
g.font = ScriptUI.newFont("Georgia","BOLDITALIC",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.g620.cb3 = win.g620.add('checkbox',undefined,'Remove any ()[]');
win.g620.cb3.value=false;
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.description ? md.description[0] : "";
if(Caption == "") continue;
var result=patt.test(Caption.toString());
if(result == true){
    var newCaption = Caption.replace(patt,win.g610.et1.text.toString());
    if(win.g620.cb3.value)  newCaption = newCaption.replace(/["'\(\)]/g, "");
    md.description='';
    md.description = newCaption;
        }
    }
}
win.show();
app.document.chooseMenuItem("PurgeCacheForSelected");
};

 

 

Likes

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 ,
May 20, 2022 May 20, 2022

Copy link to clipboard

Copied

OK, my MacBook is back! @mikejlkemp it looks like there may be a solution offered by @gregreser ? Have you tested it yet? If it works, please mark his reply as the correct answer. If you need further assistance, please let the forum know.

Likes

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 ,
May 21, 2022 May 21, 2022

Copy link to clipboard

Copied

Hi Stephen, good news about your Macbook! Afraid the solution isn't quite there, although great of @gregreser to help. This is what it is doing:

 

When you use the script on one caption, the caption disappears completely, but then if you navigate away to another program and go back, the caption comes back, minus the part chosen to remove.

 

If you then do more than one picture, again the captions completely disappear (which is a bit worrying at the time) but then if you navigate away as previously, the caption is still gone. But if you quite bridge, and restart, the captions come back, minus their removed parts.

 

So, it's a bit clunky and doesn't quite instill much confidence. So need somehow to get this working without having to quit and restart Bridge. 

 

Cheers,

 

Mike

Likes

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 ,
May 21, 2022 May 21, 2022

Copy link to clipboard

Copied

Hi again @Stephen_A_Marsh well, it looks like @gregreser has solved it. He found a piece in the script which was  stripping out the caption. I'm delighted! Mike

Likes

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 ,
May 21, 2022 May 21, 2022

Copy link to clipboard

Copied

Looking at Paul Riggott's original Find Replace In Description script, I noticed that it runs this command when it loads: app.document.chooseMenuItem("PurgeCacheForSelected");
 
I'm guessing that there was a problem with metadata edits not always displaying and that purging the cache solved that. Ineed, I experienced the same blank Description as @mikejlkemp after running Find Replace In Description. I then manually purged the cache and the edited Description displayed.
 
Riggott's script used a simple XMP write method:  md.description =  . It might be that this does not work well in Bridge 2022. I changed the script to use the xmp.serialize method and that seems to work better.
 

 

#target bridge
if( BridgeTalk.appName == "bridge" ) { 
ReplaceDescription = new MenuElement("command", "Find and Replace Description/Caption", "at the end of tools");
}
 // Load the XMP Script library
if( !xmpLib){
	if( Folder.fs == "Windows" ){
		var pathToLib = Folder.startup.fsName + "/AdobeXMPScript.dll";
	}
	else{
		var pathToLib = Folder.startup.fsName + "/AdobeXMPScript.framework";
	}
	var libfile = new File( pathToLib );
	var xmpLib = new ExternalObject("lib:" + pathToLib );
}
ReplaceDescription.onSelect = function () { 
var win = new Window( 'dialog', 'Find & Replace' ); 
//g = win.graphics;
//var myBrush = g.newBrush(g.BrushType.SOLID_COLOR, [0.99, 0.99, 0.99, 1]);
//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,'Description/Caption Editor');
win.title.alignment="fill";
var g = win.title.graphics;
g.font = ScriptUI.newFont("Georgia","BOLDITALIC",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.g620.cb3 = win.g620.add('checkbox',undefined,'Remove any ()[]');
win.g620.cb3.value=false;
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];
// Get the metadata object 
md = thumb.synchronousMetadata;
    // Get the XMP packet as a string and create the XMPMeta object
    var xmp = new XMPMeta(md.serialize());

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

        // Read existing dc:description property
        var Caption = xmp.getArrayItem(XMPConst.NS_DC,"description", 1);
        // Change existing dc:description property based on user input
        var result=patt.test(Caption.toString());
        if(result == true){
            var newCaption = Caption.toString().replace(patt,win.g610.et1.text.toString());
            if(win.g620.cb3.value)  newCaption = newCaption.replace(/["'\(\)]/g, "");
            }
		// Delete the dc:description property
		xmp.deleteProperty(XMPConst.NS_DC, "description");	
		// Populate the new dc:description property and set lang to x-default
		xmp.appendArrayItem(XMPConst.NS_DC, "description", newCaption, 0, XMPConst.ALIAS_TO_ALT_TEXT);
		xmp.setQualifier(XMPConst.NS_DC, "description[1]", "http://www.w3.org/XML/1998/namespace", "lang", "x-default");
        
/*
    // Paul Riggott's original write method
md.namespace =  "http://purl.org/dc/elements/1.1/";
var Caption = md.description ? md.description[0] : "";
if(Caption == "") continue;
var result=patt.test(Caption.toString());
if(result == true){
    var newCaption = Caption.replace(patt,win.g610.et1.text.toString());
    if(win.g620.cb3.value)  newCaption = newCaption.replace(/["'\(\)]/g, "");
    md.description='';
    md.description = newCaption;
        }
 */
 	// Write the packet back to the selected file
	var updatedPacket = xmp.serialize(XMPConst.SERIALIZE_OMIT_PACKET_WRAPPER | XMPConst.SERIALIZE_USE_COMPACT_FORMAT);
	thumb.metadata = new Metadata(updatedPacket);
    }
}
win.show();
//app.document.chooseMenuItem("PurgeCacheForSelected");
};

 

 

Likes

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 ,
May 23, 2022 May 23, 2022

Copy link to clipboard

Copied

I'm delighted to say this works absolutely fine with the latest version of Bridge 12 02 252. It's a simple and functional solution, so huge thanks to @gregreser and thanks also to @Stephen_A_Marsh for the input. This script solves and saves so much manual work. Great!

Likes

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 ,
May 23, 2022 May 23, 2022

Copy link to clipboard

Copied

@gregreser – thank you for taking an active and valuable role in the community!

Likes

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 ,
Oct 05, 2022 Oct 05, 2022

Copy link to clipboard

Copied

Hey Guys -

 

I've been trying to tweak this slightly to change 'Person Shown' which is 'PersonInImage' -

Nothing I've tried so far has worked, would you have an idea as to the fix? 

Any suggestions would be greatly appreciated.

Thanks!

J

 

if (BridgeTalk.appName == "bridge") {
FindandReplace = new MenuElement("command", "Find and Replace", "at the end of tools", "FindandReplace");
}
FindandReplace.onSelect = function () {
var win = new Window('palette', 'Find & Replace');
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, 'Find and Replace');
win.title.alignment = "fill";
var g = win.title.graphics;
g.font = ScriptUI.newFont("Georgia", "BOLDITALIC", 22);
win.p6 = win.p1.add("panel", undefined, undefined, {borderStyle: "black"}); //Replace
win.p6.preferredSize = [380, 100];
win.g580 = win.p6.add('group');
win.g580.orientation = "row";
win.g580.alignment = 'fill';
win.g580.st1 = win.g580.add('statictext', undefined, 'Choose Field');
win.g580.st1.preferredSize = [75, 20];
win.g580.dd1 = win.g580.add('dropdownlist', undefined, ["Person In Image"]);
win.g580.dd1.selection = 0;
win.g580.dd1.preferredSize = [200, 20];
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.g620.cb3 = win.g620.add('checkbox', undefined, 'Remove any ()[]');
win.g620.cb3.value = false;
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.bu2.onClick = function () {
win.close(2);
}
win.g1000.bu1.onClick = function () {
if (win.g600.et1.text == '') {
alert("No replace value has been entered!");
return;
}
win.close(0);
if (!ExternalObject.AdobeXMPScript) ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
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());
if (win.g580.dd1.selection.index == 1){//PersonInImage
md.namespace = "ptc4xmpExt";
var Caption = md.PersonInImage ? md.PersonInImage : "";
if (Caption == "") continue;
var result = patt.test(Caption.toString());
if (result == true) {
var newCaption = Caption.replace(patt, win.g610.et1.text.toString());
if (win.g620.cb3.value) newCaption = newCaption.replace(/["'\(\)]/g, "");
md.PersonInImage = '';
md.PersonInImage = newCaption;
}
}//end PersonInImage
}
}
win.show();
app.document.chooseMenuItem("PurgeCacheForSelected");

Likes

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 05, 2022 Oct 05, 2022

Copy link to clipboard

Copied

You can't just swap out one script that changes specific metadata for another; often you'll run into problems because these fields are stored and written to differently.

I tested that field and its stored as <bag> which is a type of array.

<Iptc4xmpExt:PersonInImage>
   <rdf:Bag>
      <rdf:li>abcdefg</rdf:li>
   </rdf:Bag>
</Iptc4xmpExt:PersonInImage>

 

https://extendscript.docsforadobe.dev/scripting-xmp/xmpscript-object-reference.html

Likes

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 05, 2022 Oct 05, 2022

Copy link to clipboard

Copied

@Lumigraphics is right, the first thing to look at when modifying a script is to determine if the XMP property type is the same as the property you want to substitute. There are other consideratoins too, such as separators for multiple value display and input.

 

I have a keyword add/replace script which was easy to modify because dc:subject uses a bag array just like Iptc4xmpExt:PersonInImage

 

See if this works for you:

 

 

 

#target bridge

/*
Terms and Conditions of Use:
MIT License

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

//Create a menu item within Adobe Bridge
if (BridgeTalk.appName == 'bridge') {
    var aRpSLbl = "Add-Replace Person Shown";
    var aRpSVers = "2022-10-05";
    aRpSMenuItem = MenuElement.create("command", aRpSLbl, "at the end of tools");
}

// when the menu item is clicked, run the script
aRpSMenuItem.onSelect = function () {
    aRpS();
    }
   
function aRpS(){
        // Load the XMP Script library
    if ( ExternalObject.AdobeXMPScript == undefined ) {
        ExternalObject.AdobeXMPScript = new ExternalObject( "lib:AdobeXMPScript" );
        }
    // PALETTE
    // =======
    var palette = new Window("palette"); 
        palette.text = aRpSLbl+" ("+aRpSVers+")"; 
        palette.orientation = "column"; 
        palette.alignChildren = ["center","top"]; 
        palette.spacing = 10; 
        palette.margins = 16; 

    var statictext1 = palette.add("statictext", undefined, undefined); 
        statictext1.text = "Edit Person Shown"; 

    // GROUP1
    // ======
    var group1 = palette.add("group", undefined); 
        group1.orientation = "row"; 
        group1.alignChildren = ["left","center"]; 
        group1.spacing = 10; 
        group1.margins = 0; 

    var radiobutton1 = group1.add("radiobutton", undefined, undefined); 
        radiobutton1.text = "Add"; 
        radiobutton1.value = true; 

    var radiobutton2 = group1.add("radiobutton", undefined, undefined); 
        radiobutton2.text = "Replace"; 
    /*
    var radiobutton3 = group1.add("radiobutton", undefined, undefined); 
        radiobutton3.text = "Clear"; 
    */
    // PANEL1
    // ======
    var panel1 = palette.add("panel", undefined, undefined); 
        panel1.orientation = "column"; 
        panel1.alignChildren = ["left","top"]; 
        panel1.spacing = 2; 
        panel1.margins = 10; 

    // GROUP2
    // ======
    var group2 = panel1.add("group", undefined); 
        group2.orientation = "row"; 
        group2.alignChildren = ["left","center"]; 
        group2.spacing = 10; 
        group2.margins = 0; 

    var statictext2 = group2.add("statictext", undefined, undefined); 
        statictext2.text = "Add"; 
        statictext2.preferredSize.width = 60; 
        statictext2.justify = "right"; 

    var edittext1 = group2.add('edittext {properties: {name: "edittext1"}}'); 
        edittext1.preferredSize.width = 250;
     //   edittext1.helpTip = 'Bridge separates names with a semi-colon ;\nA name can contain a comma and more than one word'; // \nA name containing a comma will use quotes "Paris, France"


    info1Btn = group2.add('button', undefined, "?");
    info1Btn.minimumSize = [24,24];
    info1Btn.maximumSize = [24,24];
    //info1Btn.alignment = 'right';
    info1Btn.helpTip = "Instructions";
    info1Btn.onClick = showinfo1Win;
        
    info1WinLabel = "About adding/replacing Person Shown";
    info1WinTextTxt =
    'Person Shown is stored as a list of individual names\n\n'+
    '      Joe\n'+
    '      Sue\n'+
    '      Mark Johnson\n'+
    '      Cutler, Michelle\n\n'+
    'Bridge displays names items separated by semicolons ;\n'+
    'Bridge displays quotes around a name item containing a comma ,\n\n'+
    '      Joe; Sue; Mark Johnson; "Cutler, Michelle"'

    function showinfo1Win(){
       var info1Win = new Window('palette', info1WinLabel);  
       info1WinText = info1Win.add('statictext', undefined, info1WinTextTxt, {multiline:true});
       if (Folder.fs == "Windows"){
        info1WinText.preferredSize = [440,220];
        }
    else{
        info1WinText.preferredSize = [520,320];
        }               
            info1Win.cancelBtn = info1Win.add('button', undefined, 'Close');
            info1Win.cancelBtn.onClick =  function(){ 
            info1Win.hide();
            info1Win.close();
            palette.active = true;
        }
       info1Win.show();
       info1Win.active = true;
    }

    // PANEL1
    // ======
    var statictext3 = panel1.add("statictext", undefined, undefined); 
        statictext3.text = "separate multiple names with semicolons ;"; 
        statictext3.indent = 70;

    // GROUP3
    // ======
    var group3 = panel1.add("group", undefined); 
        group3.orientation = "row"; 
        group3.alignChildren = ["left","center"]; 
        group3.spacing = 10; 
        group3.margins = 0; 

    var statictext4 = group3.add("statictext", undefined, undefined); 
        statictext4.text = "With"; 
        statictext4.preferredSize.width = 60; 
        statictext4.justify = "right"; 

    var edittext2 = group3.add('edittext {properties: {name: "edittext2"}}'); 
        edittext2.preferredSize.width = 250; 

    var statictext5 = panel1.add("statictext", undefined, undefined); 
        statictext5.text = "leave blank to delete name"; 
      //  statictext5.alignment = ["right","top"]; 
        statictext5.indent = 70;

    var statictext6 = palette.add("statictext", undefined, undefined, {multiline: true}); 
    statictext6.preferredSize.width = 300; 
    statictext6.preferredSize.height = 30;
    statictext6.justify = "center"; 
    statictext6.graphics.font = ScriptUI.newFont ("Helvetica", "Bold", 12);
    statictext6.graphics.foregroundColor = statictext6.graphics.newPen (statictext6.graphics.PenType.SOLID_COLOR, [0, 0.7, 0], 1);
    
    // GROUP4
    // ======
    var group4 = palette.add("group", undefined); 
        group4.orientation = "row"; 
        group4.alignChildren = ["left","top"]; 
        group4.spacing = 40; 
        group4.margins = 0; 

    var ok = group4.add("button", undefined, undefined); 
        ok.text = "Add"; 
        ok.preferredSize.width = 150;
        ok.preferredSize.height = 30;

    var cancel = group4.add("button", undefined, undefined); 
        cancel.text = "Cancel"; 

    // open window and set view to Add name
    statictext2.text = "Add"; 
    group3.visible = false;
   // statictext3.visible = true;
    statictext3.text = "separate multiple names with semicolons (;)";
    statictext5.visible=false;
    palette.show();

    // Dialog functions 
    if(app.document.selections.length == 0){
        ok.enabled = false;
        statictext6.text = "No file(s) selected. 'Done' then try again"
        };
    
    radiobutton1.onClick = function(){
        group2.visible = true;
        statictext2.text = "Add"; 
        edittext1.text = "";
        edittext2.text = "";
        group3.visible = false;
       // statictext3.visible = true;
        statictext3.text = "separate multiple names with semicolons (;)"
        statictext5.visible=false;
        ok.text = "Add"
        }

    radiobutton2.onClick = function(){
        group2.visible = true;
        statictext2.text = "Replace";
        edittext1.text = "";
        edittext2.text = "";
        group3.visible = true;
      //  statictext3.visible = false;
        statictext3.text = "name exact match";
        statictext5.visible=true;
        ok.text = "Replace"
        }
    /*
        radiobutton3.onClick = function(){
        group2.visible = false;
        group3.visible = false;
        statictext3.visible = true;
        statictext3.text = "Click 'Edit' to clear all names";
        statictext5.visible=false;
        }
    */
    // clear result text when edittext1 is clicked
    edittext1.addEventListener ("focus", function (e){statictext6.text = ""});
    
    ok.onClick = function processChange(){
    // Register XMP namespace
    var NS_IPTC_EXT = "http://iptc.org/std/Iptc4xmpExt/2008-02-29/"; 
    XMPMeta.registerNamespace (NS_IPTC_EXT, "Iptc4xmpExt");
        var Replace = edittext1.text.split('\"').join("");
        var With = edittext2.text.split('\"').join("");
     //   With.split('\"').join(""); // remove quotes used for name containing a comma
        var addKey = radiobutton1.value;
        var items = app.document.selections;
        if(items.length > 1){var fileTxt = "files"};
        else{var fileTxt = "file";}
        
      //  if(items.length == 0){alert("No item(s) selected. Close and try again."); statictext6.text = "No item(s) selected"};
        if(Replace.length == 0){alert("No name entered")};
        if(Replace.length > 0 && items.length > 0){
        /// write names to XMP
        for (var i = 0; i < items.length; i++){
            var file=new Thumbnail(items[i]);
            try{
            var xmpFile = new XMPFile(file.path, XMPConst.UNKNOWN,XMPConst.OPEN_FOR_UPDATE);
            }catch(e){
                    alert("Problem opening xmp for update:-\r" + file.path +"\r" +e.message);
                    return;
                }
            try{
            var xmp = xmpFile.getXMP();
            }catch(e){
                    alert("Problem opening xmp data:-\r"  + e.message);
                    return;
                }
            try{
            var tmpCount =  xmp.countArrayItems(NS_IPTC_EXT, "PersonInImage");
            }catch(e){
            alert("Cannot get count \r" + e.message);
            }
                if(addKey){
                  // split names separated by semicolon into an array (handle either "; " or ";")
                    var splitKeys = Replace.split('; ').join(';').split (';');
                    var keyTxt = " name";
                    if(splitKeys.length > 1){keyTxt = " names"};
                    for (var L1 = 1; L1 < (splitKeys.length + 1); L1++){
                        xmp.appendArrayItem(NS_IPTC_EXT, "PersonInImage", splitKeys[L1 - 1], 0, XMPConst.ARRAY_IS_UNORDERED);
                        }
                    statictext6.text = splitKeys.length+keyTxt+" added to "+items.length+" "+fileTxt; 
                    }
            if(tmpCount >0 && !addKey){
                var matchFound = 0;
                    for (var a =0;a<tmpCount;a++){
                        var     Person = xmp.getArrayItem(NS_IPTC_EXT, "PersonInImage", a+1);
                        if(Person == Replace && With == '') {
                            matchFound++
                            xmp.deleteArrayItem(NS_IPTC_EXT, "PersonInImage", a+1);
                            }
                        if(Person == Replace && With != ''){
                            matchFound++
                            xmp.setArrayItem(NS_IPTC_EXT, "PersonInImage", a+1,With);
                            }
                    }
                if(matchFound == 0){
                    //alert("'Replace' value was not found. No changes made.")
                    statictext6.text = "'"+Replace+ "' not found. No replacement made"; 
                    }
                else{
                    var matchTxt = " replacement";
                    if(matchFound > 1){matchTxt = " replacements"};
                    statictext6.text = matchFound+matchTxt+" made to "+items.length+" "+fileTxt; 
                    }
            }
            if (xmpFile.canPutXMP(xmp)) {
            xmpFile.putXMP(xmp);
            }else{
            alert(e.message);
                }
            xmpFile.closeFile(XMPConst.CLOSE_UPDATE_SAFELY);
            }
        } // CLOSE for (var i = 0; i < items.length; i++)
    }

    cancel.onClick = function(){
        palette.close();
        }

    }// CLOSE function aRpS()

 

Likes

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 ,
Oct 06, 2022 Oct 06, 2022

Copy link to clipboard

Copied

Thanks Guys, that worked a treat for accessing the correct field. Specifically, I work on uploading images to a DAM which cannot take " or , - , needs to be replaced with ; but bridge only recognises the names and not the characters that need to be replaced.

Is there a way to replace these characters with a script?

Attached is a screenshot for clarity.

Likes

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 ,
Oct 06, 2022 Oct 06, 2022

Copy link to clipboard

Copied

 

Likes

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 06, 2022 Oct 06, 2022

Copy link to clipboard

Copied

You'd need to copy that field, probably use a regular expression to replace characters, then write it back. So yes a script.

Likes

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 ,
Oct 06, 2022 Oct 06, 2022

Copy link to clipboard

Copied

I'm new to writing scripts - I've attempted, but to no avail. Would you be able to post the code I need?

 

Cheers,

J

Likes

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 06, 2022 Oct 06, 2022

Copy link to clipboard

Copied

@JoIIy just to be sure we get to a working solution, I need to ask about your DAM and how it imports the metadata.

Is it reading the metadata directly from each file?

Does the DAM use PersonInImage data as a single string or does it separate multiple values into a structure?

 

In your example, the current XMP data would be:

<Iptc4xmpExt:PersonInImage>
	<rdf:Bag>
		<rdf:li>Julianne Moore, Laura Brown</rdf:li>
	</rdf:Bag>
</Iptc4xmpExt:PersonInImage>

There are no quotes, those only appear in the Bridge UI to indocate that the value contains a comma or semicolon, meaning it is part of the value and not a separator. 

 

If your DAM data model can import multiple descrete values for names than we need to split them into proper XMP bag array items.

<Iptc4xmpExt:PersonInImage>
	<rdf:Bag>
		<rdf:li>Julianne Moore</rdf:li>
		<rdf:li>Laura Brown</rdf:li>
	</rdf:Bag>
</Iptc4xmpExt:PersonInImage>

 

The other consideration is the number of images you need to edit and how many changes are unique cases (different combination of names, different number of names, different separators, etc.). 

 

 

Likes

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