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

Is there a script for Find and Replace assigned Keywords?

Enthusiast ,
May 26, 2022 May 26, 2022

Copy link to clipboard

Copied

Good Morning,

I was wondering if there is a script that can find a keyword that was assigned to a phtos and replace it with a new one.

 

I know that if I reaname a keywrods, it will not be renamed in the assigned photos, and bridge will create back the the kewords that I renamed so I never do that. I usually go to find a specific keyword, change it it the photos that I found and assign the new one. But this is a lot of work. So I was thinking maybe there is a script  for that: I will crate a new keywords and in the script I will ask to find and replace the old keyword with the new one I crated.

 

I hope I manged to describe my question.

 

good day,

Shlomit 

TOPICS
How to , Keywords , Scripting

Views

264

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

Copy link to clipboard

Copied

Yes, there is. If you replace it with a new keyword, you will need to convert it to a persistent keyword if you wish for it to be part of your library. 

 

Add-Replace-Remove.png

 

// https://stackoverflow.com/questions/47797219/edit-script-for-editing-metadata-in-adobe-bridge-how-should-i-put-key-words
#target bridge

   if( BridgeTalk.appName == "bridge" ) {
keyReplace = MenuElement.create("command", "Add-Replace-Remove Keyword", "at the end of tools");
}
keyReplace.onSelect = function () {
      mainReplaceKeyword();
      }

function mainReplaceKeyword(){
if(app.version.substr(0,app.version.indexOf('.'))==1){
alert("Sorry You Need CS3 or CS4 to run this script!");
return;
    }
var dlg =
"dialog{text:'Script Interface',bounds:[100,100,500,310],"+
"panel0:Panel{bounds:[10,10,390,200] , text:'' ,properties:{borderStyle:'etched',su1PanelCoordinates:true},"+
"title:StaticText{bounds:[60,10,350,40] , text:'Add/Replace/Remove Keyword' ,properties:{scrolling:undefined,multiline:undefined}},"+
"panel1:Panel{bounds:[10,40,370,150] , text:'' ,properties:{borderStyle:'etched',su1PanelCoordinates:true},"+
"addKey:Checkbox{bounds:[20,10,160,31] , text:'Add Keyword' },"+
"statictext1:StaticText{bounds:[20,40,119,60] , text:'Replace' ,properties:{scrolling:undefined,multiline:undefined}},"+
"From:EditText{bounds:[120,40,350,60] , text:'' ,properties:{multiline:false,noecho:false,readonly:false}},"+
"statictext2:StaticText{bounds:[20,80,90,97] , text:'With' ,properties:{scrolling:undefined,multiline:undefined}},"+
"To:EditText{bounds:[120,80,350,100] , text:'' ,properties:{multiline:false,noecho:false,readonly:false}}},"+
"button0:Button{bounds:[10,160,180,181] , text:'Ok' },"+
"button1:Button{bounds:[200,160,370,181] , text:'Cancel' }}};";
var win = new Window(dlg,"Replace Keyword");
win.center();

win.panel0.title.graphics.font = ScriptUI.newFont("Times","BOLDITALIC",20);
g = win.graphics;
b=win.panel0.title.graphics;
var myBrush = g.newBrush(g.BrushType.SOLID_COLOR, [0.99, 0.99, 0.20, 1]);
g.backgroundColor = myBrush;
var myPen =b.newPen (g.PenType.SOLID_COLOR, [0.00, 0.00, 0.99, 1],lineWidth=1);
var myPen2 =b.newPen (g.PenType.SOLID_COLOR, [0.99, 0.00, 0.00, 1],lineWidth=1);
g.foregroundColor = myPen;
b.foregroundColor = myPen2;
win.panel0.panel1.From.active=true;
win.panel0.panel1.addKey.onClick = function() {
if(win.panel0.panel1.addKey.value) {
    win.panel0.panel1.statictext1.text = "New Keyword";
    win.panel0.panel1.From.active=true;
    win.panel0.panel1.statictext2.visible=false;
    win.panel0.panel1.To.visible=false;
    }
if(!win.panel0.panel1.addKey.value) {
    win.panel0.panel1.statictext1.text = "Replace";
    win.panel0.panel1.statictext2.visible=true;
    win.panel0.panel1.To.visible=true;
    win.panel0.panel1.From.active=true;
    }
}
win.center();
var done = false;
    while (!done) {
      var x = win.show();
      if (x == 0 || x == 2) {
        win.canceled = true;
        done = true;
      } else if (x == 1) {
        done = true;
       var result = valiDate();
        if(result != true) {
            alert(result);
            return;
        }else{
            var Replace = win.panel0.panel1.From.text;
            var With = win.panel0.panel1.To.text;
            var addKey = win.panel0.panel1.addKey.value;
            processKeyword(Replace,With,addKey);
        }
      }
   }

function valiDate(){
    if(win.panel0.panel1.From.text =='') return "No Keyword Entered!";
return true;
}
function processKeyword(Replace,Witha,ddKey){
try{
loadXMPScript();
}catch(e){
alert("Can not load XMPScript\r" + e.message);
    }

var items = app.document.selections;
  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(XMPConst.NS_DC, "subject");
}catch(e){
    alert("Cannot get count \r" + e.message);
    }
            if(addKey){
                xmp.appendArrayItem(XMPConst.NS_DC, "subject", Replace, 0,XMPConst.ARRAY_IS_ORDERED);
                }
if(tmpCount >0 && !addKey){
        for (var a =0;a<tmpCount;a++){
            var     Keyword = xmp.getArrayItem(XMPConst.NS_DC,'subject', a+1);
            if(Keyword == Replace && With == '') {
                xmp.deleteArrayItem(XMPConst.NS_DC,'subject', a+1);
                }
            if(Keyword == Replace && With != ''){
                xmp.setArrayItem(XMPConst.NS_DC,'subject', a+1,With);
                }
        }
}

if (xmpFile.canPutXMP(xmp)) {
xmpFile.putXMP(xmp);
}else{
alert(e.message);
    }
xmpFile.closeFile(XMPConst.CLOSE_UPDATE_SAFELY);
}
unloadXMPScript();
}
}

function loadXMPScript()
{
    var results = new XMPLibMsg("XMPScript Library already loaded", 0, false);

    if (!ExternalObject.AdobeXMPScript)
    {
        try
        {
            ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
            results.message = "XMPScript Library loaded";
        }
        catch (e)
        {
            alert("Could not load AdobeXMPScript \r" + e.message);
            results.message = "ERROR Loading AdobeXMPScript: " + e;
            results.line = e.line;
            results.error = true;
        }
    }

    return results;
}
function unloadXMPScript()
{
    var results = new XMPLibMsg("XMPScript Library not loaded", 0, false);

    if( ExternalObject.AdobeXMPScript )
    {
        try
        {
            ExternalObject.AdobeXMPScript.unload();
            ExternalObject.AdobeXMPScript = undefined;
            results.message = "XMPScript Library successfully unloaded";
        }
        catch (e)
        {
            results.message = "ERROR unloading AdobeXMPScript: " + e;
            results.line = e.line;
            results.error = true;
        }
    }

    return results;
}
function XMPLibMsg (inMessage, inLine, inError)
{
    this.message = inMessage;
    this.line = inLine;
    this.error = inError;
}

 

Select the files, then Tools > Add-Replace-Remove Keyword

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.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 ,
May 28, 2022 May 28, 2022

Copy link to clipboard

Copied

@Shlomit Heymann – so how did the script work for you?

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

Copy link to clipboard

Copied

@Stephen_A_Marsh thanks for posting this. I tried this script and it worked well. 

@Shlomit Heymann let us know if it solved your problem.

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
Enthusiast ,
Jun 03, 2022 Jun 03, 2022

Copy link to clipboard

Copied

Dear Stepehn,

I'm sorry for my late reply. In the meanwhile, I have made a terriabl mistake with the keywords, and got really under pressure and now I will have to fix many photos manually.

 

The script you created works well, but it is my fault that I did not explained what I really need. This script will create new keywords which can later defined as perssistant. But what I need is the ability to select an existed kewrod from my keywords list hirarchy and to replace it with another keyword that exsist in same or different hirarchy too without creating a new keyword. 

 

For instance: I'm taking flower photos, so I have a keywords folder for Family type, Flower Name, Color, wild flowers, succullents etc.. Each folder has sub fulders and sometimes those has more subfolders.  

 

I also have a few same keywords that appears in different hirachy and I know now it was a mistake. So I want to find the keyword in one hirarcy and replace it with a different hirarchy and this is why I need the abily to select the keywords for an existed list and also the replace. 

 

Again, Thank you so much

Shlomit

 

 

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 ,
Jun 04, 2022 Jun 04, 2022

Copy link to clipboard

Copied

@Shlomit Heymann 

 

I'm sorry to hear that you are having issues. Please do test with care before using on many images...

 

I have tried a different script, it appears to do what you require, please take a look at this animation before/after to see if it does what I believe you need:

 

find-replace.gif

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
Enthusiast ,
Jun 19, 2022 Jun 19, 2022

Copy link to clipboard

Copied

Good Morning Stephen,

The problem is that I have the same keywords in different hirarchies (It was wrong to do so but I did).

 

In your animation it finds the A1 in the A hirarchy becuase it exsit only there. But if you had another A1 in the Holiday Hirarchy (for instance), which one will it find? Or if you have another A3 in the Holiday hyrarchy too, to which A3 will be replaced?

 

This is why I wanted a possebilty to find through a specific hyrarchy otherwise It will not make the change I need. 

 

good day and thank you

Shlomit 

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

Copy link to clipboard

Copied

@Shlomit Heymann – Ah... Now I understand. Hierarchical + duplicate keywords do add to the complexity!

 

Let me think about that, all is not lost.

 

OK, I have just tried with ExifTool and it is easy to reassign the incorrect hierarchical keyword to the correct one in both the standard -XMP-dc:Subject and in the -XMP-lr:HierarchicalSubject fields.

 

A "simple" conditional command can search through a folder or sub-folders of images and check for the same hierarchical sub-keyword in the incorrect top-level keyword set and reassign the keyword to the correct sub-keyword in the correct top-level keyword.

 

@Lumigraphics or @gregreser  – do you have 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 ,
Jun 20, 2022 Jun 20, 2022

Copy link to clipboard

Copied

There are five keyword fields- two used by Lightroom, one written by a camera, one Microsoft, and dc:subject.

If you use hierarchical keywords, you won't have duplicates. A|1|a and B|1|a are different. I'd clean up keywords first and then worry about re-assigning things.

Finally, its easy to copy keywords from files and export, maybe consider doing search and replace in a text editor if its getting hairy and then reimport them.

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

Copy link to clipboard

Copied

I would export the keywords from the files and edit them in a spreadsheet. I find it easy to analyze and batch edit in a spreadsheet, so that would be my choice.

 

@Shlomit Heymann are you familiar with spreadsheets (Excel or Google Sheets)? There are several scripts to export/import via Bridge (I have one I can share) as well as ExifTool.

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
Enthusiast ,
Jun 20, 2022 Jun 20, 2022

Copy link to clipboard

Copied

Good Morning and thank  you 🙂

Sort of. I did download once a script so I can fix a spreadshit, but it was many years ago and I'm not sure I remember. But maybe I can learn. Looking at bridge I see that have installed "VRA Core Metadata" and "Metadata (DIY Custom Metadata). I think I have corresponded back than with the script editor as I had problem with Hebrew keywords and he fixed something in the script, it was many years ago. 

 

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

Copy link to clipboard

Copied

One can also do this manually. Setup Bridge to show content from all sub-folders and to hide folders, then use Find as follows, select all found/filtered files and swap over the keywords:

 

manual.png

 

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

Copy link to clipboard

Copied

Yes, I think you might be able to use existing Bridge tools to accomplish your goals as @Stephen_A_Marsh suggests. You seem to know what the incorrect keywords are, so you could use the advanced search to find them and then manually edit the keywords in the Bridge metadata panel. 

There are always many ways to approach these problems. Let us know if our suggestions are helpful because you know your metadata best.

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

Copy link to clipboard

Copied

@Shlomit Heymann  – Just to confirm, does the following illustrate the issue?

 

sub-keywords.png

 

So you need to find all images that use Test-B|Sub-Test-A and change them to Test-A|Sub-Test-A ?

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
Enthusiast ,
Jun 20, 2022 Jun 20, 2022

Copy link to clipboard

Copied

Good Morning Stephen and everybody who are trying to help.

You are so kind! Thank you.

Yes, This illustrates the issue. 

Shlomit 🤗

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

Copy link to clipboard

Copied

Here is the conditional ExifTool command-line code from my previous example (Mac):

 

exiftool -if '$XMP-dc:Subject eq "Test-B|Sub-Test-A"' -XMP-dc:Subject='Test-A|Sub-Test-A' -execute -if '$XMP-lr:HierarchicalSubject eq "Test-B|Sub-Test-A"' -XMP-lr:HierarchicalSubject='Test-A|Sub-Test-A' -execute -common_args 'PATH TO FILE OR FOLDER'

 

This command is formatted for the Mac OS. For Windows, the single straight quotes ' would need to be swapped for double straight quotes " and the double straight quotes would need to be swapped for single straight quotes. Here it is for Win:

 

exiftool -if "$XMP-dc:Subject eq 'Test-B|Sub-Test-A'" -XMP-dc:Subject="Test-A|Sub-Test-A" -execute -if "$XMP-lr:HierarchicalSubject eq 'Test-B|Sub-Test-A'" -XMP-lr:HierarchicalSubject="Test-A|Sub-Test-A" -execute -common_args "PATH TO FILE OR FOLDER"

 

The 'PATH TO FILE OR FOLDER' would need to be changed to your test folder or file path (always backup and or work on duplicates). 

 

Files successfully modified will create a backup copy with _original at the end of the filename, such as myFile.jpg_original and once you are happy a further command could be added to not create these _original backup files.

 

It is also possible to recursively scan into all sub-directories under a main/root directory and to also exclude certain file types and or sub-directories from being processed.

 

ExifTool is powerful, however, not everybody is comfortable with using command-line interfaces.

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
Enthusiast ,
Jun 21, 2022 Jun 21, 2022

Copy link to clipboard

Copied

Thank you. Im on Mac but I don't know (yet) what to do with it... 🙂 I will consulty with a friend who is better than me in these things.

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

Copy link to clipboard

Copied

Download and install ExifTool from the link previously provided.

 

Run Terminal.app

 

Paste in the code above*, making sure there is a space at the end, but don't paste in 'PATH TO FILE OR FOLDER'

 

Then you can drag your test file or test folder into the Terminal window and press return/enter. Always work on copies while you get the hang of things.

 

*You will obviously need to change the hierarchical keywords.

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

Copy link to clipboard

Copied

LATEST

And as a final note, the first example below is a production script that grabs keywords from dc:subject and lr:hierarchicalKeywords, sorts, removes duplicates, and writes them back into those two namespaces.

The second example is a production script to capture keywords from files and write to a text file for import. Just as an example of whats involved if you work with keywords in a script.

/*
Utility Pack Scripts created by David M. Converse ©2018-21

This script removes duplicate and empty keyword tags and rewrites in alphabetical order

Last modifed 6/11/2021

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{

    //create menu
        var kwOpt = MenuElement.create('command', 'Keyword Optimizer', 'at the end of Tools');

        kwOpt.onSelect = function(){
            var kwList = app.document.selections;
            var i = 0;
            var j = 1;
            var k = 1;
            var kw_clean = []; //optimized keywords array
            if (ExternalObject.AdobeXMPScript == undefined)  ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
            for(i = 0; i < kwList.length; i++){ //loop through selected files
                if(kwList[i].hasMetadata){ //only process files with metadata
                    k = 1;
                    kw_clean = [];
                    //XMP stores keywords in three namespaces. We don't process the Microsoft keyword namespace.
                    var kw = kwList[i].synchronousMetadata.read(XMPConst.NS_DC, 'subject').toString();
                    var lrkw = kwList[i].synchronousMetadata.read('http://ns.adobe.com/lightroom/1.0/', 'hierarchicalSubject').toString();
                    if(kw != '' || lrkw != ''){ //at least one namespace has keywords
                        kw = kw.split(','); //make arrays out of keyword string
                        lrkw = lrkw.split(',');
                        kw = kw.concat(lrkw); //place all keywords in one array and sort
                        kw.sort();
                        if(kw[0] != ''){
                            kw_clean[0] = kw[0];
                            }
                        else{ //flag empty keywords
                            k = 0;
                            }
                        for(j = 1; j < kw.length; j++){ //eliminate duplicates and write into new array
                            if(kw[(j - 1)] != kw[j] && kw[j] != ''){
                                kw_clean[k] = kw[j];
                                k++;
                                }
                            }
                        var md = kwList[i].synchronousMetadata;
                        var xmp = new XMPMeta(md.serialize());
                        //delete old keywords in both namespaces
                        XMPUtils.removeProperties(xmp, XMPConst.NS_DC, 'subject', XMPConst.REMOVE_ALL_PROPERTIES);
                        XMPUtils.removeProperties(xmp, 'http://ns.adobe.com/lightroom/1.0/', 'hierarchicalSubject', XMPConst.REMOVE_ALL_PROPERTIES);
                        for(j = 0; j < kw_clean.length; j++){ //write optimized list of keywords to both spaces
                            xmp.appendArrayItem(XMPConst.NS_DC, 'subject', kw_clean[j], 0,XMPConst.PROP_IS_ARRAY);
                            xmp.appendArrayItem('http://ns.adobe.com/lightroom/1.0/', 'hierarchicalSubject', kw_clean[j], 0, XMPConst.PROP_IS_ARRAY);
                            }
                        var updatedPacket = xmp.serialize(XMPConst.SERIALIZE_OMIT_PACKET_WRAPPER | XMPConst.SERIALIZE_USE_COMPACT_FORMAT);
                        kwList[i].metadata = new Metadata(updatedPacket);
                        }
                    }
                }
            alert('Keyword Optimization complete.');
            }
        }
    catch(e){
        alert(e + ' ' + e.line);
        }
    }

 

/*
Utility Pack Scripts created by David M. Converse ©2018-21

This script reads keywords from files and saves to a text file for import into Bridge

Last modifed 2/24/2021

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 KeywordCapture = 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 kwCap = MenuElement.create('command', 'Keyword Capture', 'at the end of utilPack');
            }
        else{
            var kwCap = MenuElement.create('command', 'Keyword Capture', 'at the end of Tools');
            }

        kwCap.onSelect = function(){
            var kwList = app.document.selections;
            var i = 0; //counters
            var j = 1;
            var k = 1;
            var l = 0;
            var kw_clean = []; //optimized keywords array
            var kw_line = ''; //keyword
            var kw_tabs = []; //hierarchy depth
            var kw_leading = ''; //exported file requires tab delimiter for hierarchical keywords
            var kwCapLogFile = File(''); //file to write list to
            kwCapLogFile = new File('~/Desktop/kwCapture.txt').saveDlg('Create Keyword Capture File', '*.txt'); //create text file
            kwCapLogFile.open('w:');
            if (ExternalObject.AdobeXMPScript == undefined)  ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
            for(i = 0; i < kwList.length; i++){ //loop through selected files
                if(kwList[i].hasMetadata){ //only process files with metadata
                    k = 1;
                    kw_clean = [];
                    kw_tabs = [];
                    //XMP stores keywords in three namespaces. We don't process the Microsoft keyword namespace.
                    var kw = kwList[i].synchronousMetadata.read(XMPConst.NS_DC, 'subject').toString();
                    var lrkw = kwList[i].synchronousMetadata.read('http://ns.adobe.com/lightroom/1.0/', 'hierarchicalSubject').toString();
                    if(kw != '' || lrkw != ''){ //at least one namespace has keywords
                        kw = kw.split(','); //make arrays out of keyword string
                        lrkw = lrkw.split(',');
                        kw = kw.concat(lrkw); //place all keywords in one array and sort
                        kw.sort();
                        if(kw[0] != ''){
                            kw_clean[0] = kw[0];
                            }
                        else{ //flag empty keywords
                            k = 0;
                            }
                        for(j = 1; j < kw.length; j++){ //eliminate duplicates and write into new array
                            if(kw[(j - 1)] != kw[j] && kw[j] != ''){
                                kw_clean[k] = kw[j];
                                k++;
                                }
                            }
                        for(j = 0; j < kw_clean.length; j++){ //write optimized list of keywords to file
                            kw_leading = ''; //reset leading tabs
                            kw_tabs = kw_clean[j].match(/\|/g); //how deep is the hierarchy
                            if(kw_tabs != null){ //hierarchical kw
                                for(l = 0; l < kw_tabs.length; l++){
                                    kw_clean[j] = kw_clean[j].replace('|', '\r' + kw_leading + '\t'); //we process "|" as a delimiter, edit script to use others
                                    kw_leading = kw_leading + '\t'; //each new level requires one more leading tab
                                    }
                                }
                            if(kw_line != ''){
                                kw_line = kw_line + '\r' + kw_clean[j];
                                }
                            else{ //first line for file, don't add extra return
                                kw_line = kw_clean[j];
                                }
                            }
                        kwCapLogFile.writeln(kw_line); //write to file
                        kw_line = ''; //reset for next file
                        }
                    }
                }
            kwCapLogFile.close();
            kwCapLogFile.open('r:');
            var kwFin = kwCapLogFile.read();
            kwCapLogFile.close();
            kwCapLogFile.open('w:');
            kwFin = kwFin.replace(/\n\t/g, '\t');
            kwFin = kwFin.split('\n');
            kwFin = kwFin.sort();
            for(i = 0; i < kwFin.length; i++){
                if(kwFin[i] == kwFin[i + 1]){
                    kwFin[i] = '';
                    }
                }
            kwFin = kwFin.sort();
            kwFin = kwFin.join('\r');
            kwFin = kwFin.replace(/\r\r/g, '');
            kwFin = kwFin.replace(/\t/g, '\r\t');
            kwFin = kwFin.replace(/\t\r/g, '\t');
            kwCapLogFile.write(kwFin);
            kwCapLogFile.close();
            alert('Keyword capture completed');
            }
        }
    catch(e){
        alert(e + ' ' + e.line);
        }
    }

 

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