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

How do I copy keywords “backwards?”

Community Beginner ,
Aug 28, 2013 Aug 28, 2013

Copy link to clipboard

Copied

I added Keywords to many jpg files when I should have added them to their scanned source files (tifs). Is there an efficient way to copy them from the jpg versions to their tif “originals?” Except for their suffixes, they are identically named. Obviously the keywords assigned to any one jpg can be dragged to its tif version (or to any any other image file). But I have about nine thousand of them, each with its own set of keywords, and each with its own tif source file (with no keywords). Is there a way to automate this? Is there a way to tell the jpgs to transfer their metadata to other files with the same names (minus prefix) or to any other files?

I’m working in Bridge3 OSX, but will use any software that can do this efficiently. And I will learn whatever scripting is necessary if that’s what it takes.

TOPICS
Scripting

Views

4.6K

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

Enthusiast , Sep 02, 2013 Sep 02, 2013

The problem is that you haven't set Textedit to use plain text, as the error message is showing control characters, denoted by the rtf.

This is why it is best to use ExtendScript Toolkit that is installed with Photoshop.

You should find it in <hard drive>/Applications/Utilities/Adobe Utilities

Votes

Translate

Translate
Advocate ,
Aug 30, 2013 Aug 30, 2013

Copy link to clipboard

Copied

I expect the regulars here can provide a far better answer than I can as a Bridge-scripting noob, but since no one else has answered I'll say "This sounds like a job for ExifTool."  In fact, the ExifTool forum has a thread "Copy Meta-Data from 1 set of files to another."  But for all I know, scripting Bridge might be easier.

David

Message was edited by: David W. Goodrich for typo in URL

Votes

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 ,
Aug 30, 2013 Aug 30, 2013

Copy link to clipboard

Copied

Unfortunately, that solution appears not to apply to the Mac OS platform.

Votes

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
Advocate ,
Aug 31, 2013 Aug 31, 2013

Copy link to clipboard

Copied

ExifTool is is about as platform-independent as software can be.  There are graphical user interfaces available, but I've only used it from the command line in Windows.  It's been a long time since I did anything with OSX's Terminal, but I assume ExifTool works similarly there.  ExifTool can do a hell of a lot, but getting it to do what you want in a single command entails precisely controlling the command with a series of parameters (though you can combine some in callable arguments files).  All this can be pretty intimidating at first, and part of the ethos, seemingly, is that you are expected to learn by doing: the homepage quotes an Adobe forum contributor, "Insanely great tool with a long learning curve."  I expect ExifTool can do what you want under OSX, and I've gotten far enough along the learning curve that I'd try it over Bridge scripting, but I expect some of the experts here could do it more easily with Bridge.

David

Votes

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 ,
Sep 01, 2013 Sep 01, 2013

Copy link to clipboard

Copied

This thread may have the code you require?

http://forums.adobe.com/thread/710440

Votes

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 ,
Sep 01, 2013 Sep 01, 2013

Copy link to clipboard

Copied

This is not something I have done before, but I will attempt it this week. Thanks.

Votes

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 ,
Sep 01, 2013 Sep 01, 2013

Copy link to clipboard

Copied

I have modified that script, so hopefully it should now work for you.

#target bridge  

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

var newMenuData = new MenuElement( "menu", "Copy_Metadata", "after Help", "myMetaData" );

var newDataCommand = new MenuElement( "command", "Copy Metadata", "at the end of myMetaData" , "zxcv" );

}

newDataCommand.onSelect = function () {

      renamePutXMP();

      }

function renamePutXMP(){

var win = new Window('dialog','Copy Metadata');

g = win.graphics;

var myBrush = g.newBrush(g.BrushType.SOLID_COLOR, [0.99, 0.99, 0.99, 1]);

g.backgroundColor = myBrush;

win.alignChildren="row";

win.g10 = win.add('group');

win.g10.orientation = "row";

win.title = win.g10.add('statictext',undefined,'Copy Metadata');

win.title.alignment="bottom";

var g = win.title.graphics;

g.font = ScriptUI.newFont("Georgia","BOLDITALIC",22);

win.p1= win.add("panel", undefined, undefined, {borderStyle:"black"});

win.p1.alignChildren="fill";

win.g5 =win.p1.add('group');

win.g5.spacing=10;

win.g5.st1 = win.g5.add('statictext',undefined,'Source Files');

win.g5.st1.preferredSize=[100,20];

win.g5.et1 = win.g5.add('edittext');

win.g5.et1.preferredSize=[250,20];

win.g5.et1.enabled=false;

win.g5.bu1 = win.g5.add('button',undefined,'Browse');

win.g10 =win.p1.add('group');

win.g10.spacing=10;

win.g10.st1 = win.g10.add('statictext',undefined,'Destination Files');

win.g10.st1.preferredSize=[100,20];

win.g10.et1 = win.g10.add('edittext');

win.g10.et1.preferredSize=[250,20];

win.g10.et1.enabled=false;

win.g10.bu1 = win.g10.add('button',undefined,'Browse');

win.g15 =win.p1.add('group');

win.g15.orientation='row';

win.g15.alignment="top";

win.g15.spacing=10;

win.g15.bu1 = win.g15.add('button',undefined,'Process');

win.g15.bu1.preferredSize=[200,30];

win.g15.bu2 = win.g15.add('button',undefined,'Cancel');

win.g15.bu2.preferredSize=[200,30];

win.g5.bu1.onClick=function(){

     rawFolder = Folder.selectDialog("Please select the Source folder",app.document.presentationPath);

     if(rawFolder !=null){

        win.g5.et1.text =  decodeURI(rawFolder.fsName);

        }

}

win.g10.bu1.onClick=function(){

     destinationFolder = Folder.selectDialog("Please select the destination files folder",app.document.presentationPath);

     if(destinationFolder !=null){

        win.g10.et1.text =  decodeURI(destinationFolder.fsName);

        }

}

win.g15.bu1.onClick=function(){

    if(win.g5.et1.text == ''){

        alert("No Source folder selected!");

        return;

        }

    if(win.g10.et1.text == ''){

        alert("No Destination folder selected!");

        return;

        }

    win.close(1);

    process(rawFolder,destinationFolder);

}

win.center();

win.show();

}

function process(rawFolder,destinationFolder){

var rawFiles = rawFolder.getFiles (/\.(jpg)$/i);

if(!rawFiles.length){alert("There are no source files to be processed!"); return;}

for (var a in rawFiles){

var Name = decodeURI(rawFiles.name).replace(/\.[^\.]+$/, '');

var destFile = File(destinationFolder + "/" + Name + ".tif");

if(destFile.exists) updateMetaData(rawFiles,destFile);

    }

}

function updateMetaData(sourceFile,destFile){

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

sourceFile = new Thumbnail(File(sourceFile));

destFile = new Thumbnail(File(destFile));

var md = sourceFile.synchronousMetadata;

var source = new XMPMeta( md.serialize() );

var md2 = destFile.synchronousMetadata;

var dest = new XMPMeta( md2.serialize() );

try{

copySchema( source, dest,XMPConst.NS_DC,[]);

copySchema( source, dest,XMPConst.NS_XMP_RIGHTS,[]);

copySchema( source, dest,XMPConst.NS_IPTC_CORE,[]);

copySchema( source, dest,XMPConst.NS_PHOTOSHOP,[]);

var updatedPacket = dest.serialize(XMPConst.SERIALIZE_OMIT_PACKET_WRAPPER | XMPConst.SERIALIZE_USE_COMPACT_FORMAT);

destFile.metadata = new Metadata(updatedPacket);

app.document.refresh();

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

}

function copySchema( source, dest, namespace, omitProps ) { 

    var propIter = source.iterator(XMPConst.ITERATOR_JUST_CHILDREN | XMPConst.ITERATOR_JUST_LEAF_NAME, namespace, "" );

    var prop = propIter.next();

    var prefix = XMPMeta.getNamespacePrefix( namespace );

    while(prop) {           

        var name = prop.path.substring( prefix.length );    

         if(omitProps != undefined) var copy = !contains( omitProps, name);

        if( copy ) {

            try{

            XMPUtils.duplicateSubtree( source, dest, namespace, prop.path,namespace, prop.path, 0 );       

            }catch(e){}

        }

        prop = propIter.next();

    }        

}

function contains( arr, member ){

    var r = false;

    for( var i = 0; i < arr.length &! r; ++i  ) {

        r = arr == member;

    }

    return r;

}

#target bridge  

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

var newMenuData = new MenuElement( "menu", "Copy_Metadata", "after Help", "myMetaData" );

var newDataCommand = new MenuElement( "command", "Copy Metadata", "at the end of myMetaData" , "zxcv" );

}

newDataCommand.onSelect = function () {

      renamePutXMP();

      }

function renamePutXMP(){

var win = new Window('dialog','Copy Metadata');

g = win.graphics;

var myBrush = g.newBrush(g.BrushType.SOLID_COLOR, [0.99, 0.99, 0.99, 1]);

g.backgroundColor = myBrush;

win.alignChildren="row";

win.g10 = win.add('group');

win.g10.orientation = "row";

win.title = win.g10.add('statictext',undefined,'Copy Metadata');

win.title.alignment="bottom";

var g = win.title.graphics;

g.font = ScriptUI.newFont("Georgia","BOLDITALIC",22);

win.p1= win.add("panel", undefined, undefined, {borderStyle:"black"});

win.p1.alignChildren="fill";

win.g5 =win.p1.add('group');

win.g5.spacing=10;

win.g5.st1 = win.g5.add('statictext',undefined,'Source Files');

win.g5.st1.preferredSize=[100,20];

win.g5.et1 = win.g5.add('edittext');

win.g5.et1.preferredSize=[250,20];

win.g5.et1.enabled=false;

win.g5.bu1 = win.g5.add('button',undefined,'Browse');

win.g10 =win.p1.add('group');

win.g10.spacing=10;

win.g10.st1 = win.g10.add('statictext',undefined,'Destination Files');

win.g10.st1.preferredSize=[100,20];

win.g10.et1 = win.g10.add('edittext');

win.g10.et1.preferredSize=[250,20];

win.g10.et1.enabled=false;

win.g10.bu1 = win.g10.add('button',undefined,'Browse');

win.g15 =win.p1.add('group');

win.g15.orientation='row';

win.g15.alignment="top";

win.g15.spacing=10;

win.g15.bu1 = win.g15.add('button',undefined,'Process');

win.g15.bu1.preferredSize=[200,30];

win.g15.bu2 = win.g15.add('button',undefined,'Cancel');

win.g15.bu2.preferredSize=[200,30];

win.g5.bu1.onClick=function(){

     rawFolder = Folder.selectDialog("Please select the Source folder",app.document.presentationPath);

     if(rawFolder !=null){

        win.g5.et1.text =  decodeURI(rawFolder.fsName);

        }

}

win.g10.bu1.onClick=function(){

     destinationFolder = Folder.selectDialog("Please select the destination files folder",app.document.presentationPath);

     if(destinationFolder !=null){

        win.g10.et1.text =  decodeURI(destinationFolder.fsName);

        }

}

win.g15.bu1.onClick=function(){

    if(win.g5.et1.text == ''){

        alert("No Source folder selected!");

        return;

        }

    if(win.g10.et1.text == ''){

        alert("No Destination folder selected!");

        return;

        }

    win.close(1);

    process(rawFolder,destinationFolder);

}

win.center();

win.show();

}

function process(rawFolder,destinationFolder){

var rawFiles = rawFolder.getFiles (/\.(jpg)$/i);

if(!rawFiles.length){alert("There are no source files to be processed!"); return;}

for (var a in rawFiles){

var Name = decodeURI(rawFiles.name).replace(/\.[^\.]+$/, '');

var destFile = File(destinationFolder + "/" + Name + ".tif");

if(destFile.exists) updateMetaData(rawFiles,destFile);

    }

}

function updateMetaData(sourceFile,destFile){

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

sourceFile = new Thumbnail(File(sourceFile));

destFile = new Thumbnail(File(destFile));

var md = sourceFile.synchronousMetadata;

var source = new XMPMeta( md.serialize() );

var md2 = destFile.synchronousMetadata;

var dest = new XMPMeta( md2.serialize() );

try{

copySchema( source, dest,XMPConst.NS_DC,[]);

copySchema( source, dest,XMPConst.NS_XMP_RIGHTS,[]);

copySchema( source, dest,XMPConst.NS_IPTC_CORE,[]);

copySchema( source, dest,XMPConst.NS_PHOTOSHOP,[]);

var updatedPacket = dest.serialize(XMPConst.SERIALIZE_OMIT_PACKET_WRAPPER | XMPConst.SERIALIZE_USE_COMPACT_FORMAT);

destFile.metadata = new Metadata(updatedPacket);

app.document.refresh();

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

}

function copySchema( source, dest, namespace, omitProps ) { 

    var propIter = source.iterator(XMPConst.ITERATOR_JUST_CHILDREN | XMPConst.ITERATOR_JUST_LEAF_NAME, namespace, "" );

    var prop = propIter.next();

    var prefix = XMPMeta.getNamespacePrefix( namespace );

    while(prop) {           

        var name = prop.path.substring( prefix.length );    

         if(omitProps != undefined) var copy = !contains( omitProps, name);

        if( copy ) {

            try{

            XMPUtils.duplicateSubtree( source, dest, namespace, prop.path,namespace, prop.path, 0 );       

            }catch(e){}

        }

        prop = propIter.next();

    }        

}

function contains( arr, member ){

    var r = false;

    for( var i = 0; i < arr.length &! r; ++i  ) {

        r = arr == member;

    }

    return r;

}

Votes

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 ,
Sep 02, 2013 Sep 02, 2013

Copy link to clipboard

Copied

Thanks Phil, I hope this isn’t beyond me. Is this script for entering directly into OSX Terminal? Can I copy & paste?

Votes

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 ,
Sep 02, 2013 Sep 02, 2013

Copy link to clipboard

Copied

The script can not be run from the terminal, to install and run the script, this should help.

Copy and paste the script into ExtendScript Toolkit or a plain text editor, save the file  with a .jsx extension.

To find the folder to where it needs to be saved, open Bridge, Adobe Bridge menu - Preferences - Startup Scripts

At the bottom click the "Reveal Button" this will open the folder where the script should be saved.

Re-start Bridge and accept the new script, there will then be a new menu item "Copy Metadata" where you can select the script, then select the folders where the jpg and tif files reside. The script should then do the rest.

Best of luck.

Votes

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 ,
Sep 02, 2013 Sep 02, 2013

Copy link to clipboard

Copied

I copied the forum text of the script, pasted it into TextEdit, titled it Copy Metadata, and changed the extension to .jsx. I added it to the Startup Scripts folder revealed in the Startup Script Preferences and checked its box. It now appears in Prefs whenever I restart Bridge.

However, upon restart, a message says an error occurred while running the new script. It suggests updating Bridge, but the updater under the Help menu no longer seems to work. I am running Bridge 3.0.0.464 CS4 (Mac). I will look around to make sure I have the latest upgrade.

The message also says the script has been disabled, “but can be re-enabled in the Startup Scripts section of Preferences.” I tried that several times, but no go. The message ends with:

“.../Startup Scripts/Copy Metadata.jsx Line1:{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf390 Syntax error”

Could I have erred in preparing the .jsx text file?

Votes

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 ,
Sep 02, 2013 Sep 02, 2013

Copy link to clipboard

Copied

The problem is that you haven't set Textedit to use plain text, as the error message is showing control characters, denoted by the rtf.

This is why it is best to use ExtendScript Toolkit that is installed with Photoshop.

You should find it in <hard drive>/Applications/Utilities/Adobe Utilities

Votes

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 ,
Sep 02, 2013 Sep 02, 2013

Copy link to clipboard

Copied

I reset TextEdit to plain text, Bridge accepted the script, and it works better than magic. You have saved me many hours.

P. S. Can this script be edited to copy keywords from jpg to psd?

Votes

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 ,
Sep 02, 2013 Sep 02, 2013

Copy link to clipboard

Copied

Yes, you can change line 81.

var destFile = File(destinationFolder + "/" + Name + ".tif");

to

var destFile = File(destinationFolder + "/" + Name + ".psd");

and it will do the same as it did for the tif files.

Much better than doing one by one

Votes

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 ,
Sep 02, 2013 Sep 02, 2013

Copy link to clipboard

Copied

Especially when you have thousands. Thanks again.

Votes

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 ,
Sep 04, 2013 Sep 04, 2013

Copy link to clipboard

Copied

I am unable to copy Keywords from jpg to psd files after changing tif to psd in line 81. Is there more to it?

Votes

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
Advisor ,
Sep 05, 2013 Sep 05, 2013

Copy link to clipboard

Copied

I followed this discussion with great interest as I wanted to do the same with thousands of files except that my destination files were .dng files.

I changed "tif" to "dng" in line 81.

The script runs without error but unfortunately the keywords in the destination files are not updated.

So close, yet so far!

Out of curiosity, the script name in the menu bar appears twice for some reason - but just noticed that the whole of the script seems to duplicated!

Votes

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 ,
Sep 05, 2013 Sep 05, 2013

Copy link to clipboard

Copied

I have tested this and it seems to work with PSD files. Added dropdown list so you can choose the file types for source and destination.

Good luck.

#target bridge  

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

if (!MenuElement.find ('myMetaData')){

var newMenuData = new MenuElement( "menu", "Metadata", "after Help", "myMetaData" );}

if (!MenuElement.find ('zxcv1')){

var newDataCommand = new MenuElement( "command", "Copy Metadata", "at the end of myMetaData" , "zxcv1" );}

}

newDataCommand.onSelect = function () {

      renamePutXMP();

      }

function renamePutXMP(){

var win = new Window('dialog','Copy Metadata');

g = win.graphics;

var myBrush = g.newBrush(g.BrushType.SOLID_COLOR, [0.99, 0.99, 0.99, 1]);

g.backgroundColor = myBrush;

win.alignChildren="row";

win.g10 = win.add('group');

win.g10.orientation = "row";

win.title = win.g10.add('statictext',undefined,'Copy Metadata');

win.title.alignment="bottom";

var g = win.title.graphics;

g.font = ScriptUI.newFont("Georgia","BOLDITALIC",22);

win.p1= win.add("panel", undefined, undefined, {borderStyle:"black"});

win.p1.alignChildren="fill";

var fileType = ["jpg","tif","psd","dng"];

win.g2 =win.p1.add('group');

win.g2.spacing=10;

win.g2.st1 = win.g2.add('statictext',undefined,'Source File Type');

win.g2.dd1 = win.g2.add('dropdownlist',undefined,fileType);

win.g2.dd1.selection=0;

win.g2.st2 = win.g2.add('statictext',undefined,'Destination File Type');

win.g2.dd2 = win.g2.add('dropdownlist',undefined,fileType);

win.g2.dd2.selection=1;

win.g5 =win.p1.add('group');

win.g5.spacing=10;

win.g5.st1 = win.g5.add('statictext',undefined,'Source Files');

win.g5.st1.preferredSize=[100,20];

win.g5.et1 = win.g5.add('edittext');

win.g5.et1.preferredSize=[250,20];

win.g5.et1.enabled=false;

win.g5.bu1 = win.g5.add('button',undefined,'Browse');

win.g10 =win.p1.add('group');

win.g10.spacing=10;

win.g10.st1 = win.g10.add('statictext',undefined,'Destination Files');

win.g10.st1.preferredSize=[100,20];

win.g10.et1 = win.g10.add('edittext');

win.g10.et1.preferredSize=[250,20];

win.g10.et1.enabled=false;

win.g10.bu1 = win.g10.add('button',undefined,'Browse');

win.g15 =win.p1.add('group');

win.g15.orientation='row';

win.g15.alignment="top";

win.g15.spacing=10;

win.g15.bu1 = win.g15.add('button',undefined,'Process');

win.g15.bu1.preferredSize=[200,30];

win.g15.bu2 = win.g15.add('button',undefined,'Cancel');

win.g15.bu2.preferredSize=[200,30];

win.g5.bu1.onClick=function(){

     rawFolder = Folder.selectDialog("Please select the Source folder",app.document.presentationPath);

     if(rawFolder !=null){

        win.g5.et1.text =  decodeURI(rawFolder.fsName);

        }

}

win.g10.bu1.onClick=function(){

     destinationFolder = Folder.selectDialog("Please select the destination files folder",app.document.presentationPath);

     if(destinationFolder !=null){

        win.g10.et1.text =  decodeURI(destinationFolder.fsName);

        }

}

win.g15.bu1.onClick=function(){

    if(win.g5.et1.text == ''){

        alert("No Source folder selected!");

        return;

        }

    if(win.g10.et1.text == ''){

        alert("No Destination folder selected!");

        return;

        }

    if(win.g2.dd1.selection.index == win.g2.dd2.selection.index ){

        if(win.g5.et1.text == win.g5.et2.text){

            alert("You can not copy the same data to itself!");

            return;

            }

        }

    win.close(1);

    process(rawFolder,destinationFolder);

}

win.center();

win.show();

function process(rawFolder,destinationFolder){

var rawFiles = rawFolder.getFiles ("*."+win.g2.dd1.selection.text);

if(!rawFiles.length){alert("There are no source files to be processed!"); return;}

for (var a in rawFiles){

var Name = decodeURI(rawFiles.name).replace(/\.[^\.]+$/, '');

var destFile = File(destinationFolder + "/" + Name + "."+win.g2.dd2.selection.text);

if(destFile.exists) updateMetaData(rawFiles,destFile);

    }

}

function updateMetaData(sourceFile,destFile){

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

sourceFile = new Thumbnail(File(sourceFile));

destFile = new Thumbnail(File(destFile));

var md = sourceFile.synchronousMetadata;

var source = new XMPMeta( md.serialize() );

var md2 = destFile.synchronousMetadata;

var dest = new XMPMeta( md2.serialize() );

try{

copySchema( source, dest,XMPConst.NS_DC,[]);

copySchema( source, dest,XMPConst.NS_XMP_RIGHTS,[]);

copySchema( source, dest,XMPConst.NS_IPTC_CORE,[]);

copySchema( source, dest,XMPConst.NS_PHOTOSHOP,[]);

var updatedPacket = dest.serialize(XMPConst.SERIALIZE_OMIT_PACKET_WRAPPER | XMPConst.SERIALIZE_USE_COMPACT_FORMAT);

destFile.metadata = new Metadata(updatedPacket);

app.document.refresh();

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

}

function copySchema( source, dest, namespace, omitProps ) { 

    var propIter = source.iterator(XMPConst.ITERATOR_JUST_CHILDREN | XMPConst.ITERATOR_JUST_LEAF_NAME, namespace, "" );

    var prop = propIter.next();

    var prefix = XMPMeta.getNamespacePrefix( namespace );

    while(prop) {           

        var name = prop.path.substring( prefix.length );    

         if(omitProps != undefined) var copy = !contains( omitProps, name);

        if( copy ) {

            try{

            XMPUtils.duplicateSubtree( source, dest, namespace, prop.path,namespace, prop.path, 0 );       

            }catch(e){}

        }

        prop = propIter.next();

    }        

}

function contains( arr, member ){

    var r = false;

    for( var i = 0; i < arr.length &! r; ++i  ) {

        r = arr == member;

    }

    return r;

}

Votes

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
Advisor ,
Sep 05, 2013 Sep 05, 2013

Copy link to clipboard

Copied

Thanks for your efforts.

I have tested this with dng source files and jpg destination files and it works just great with one proviso I'm afraid.

If the destination files have NO keyword data then the copying of keywords from source to destination works fine.

If the destination files have DIFFERENT keyword data from the source files then no copying of keywords takes place.

Is there any way around this?

Votes

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 ,
Sep 05, 2013 Sep 05, 2013

Copy link to clipboard

Copied

I have added a checkbox to clear existing metadata so that the new metadata can be input, could you please test this version.

#target bridge 

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

if (!MenuElement.find ('myMetaData')){

var newMenuData = new MenuElement( "menu", "Metadata", "after Help", "myMetaData" );}

if (!MenuElement.find ('zxcv1')){

var newDataCommand = new MenuElement( "command", "Copy Metadata", "at the end of myMetaData" , "zxcv1" );}

}

newDataCommand.onSelect = function () {

      renamePutXMP();

      }

function renamePutXMP(){

var win = new Window('dialog','Copy Metadata');

g = win.graphics;

var myBrush = g.newBrush(g.BrushType.SOLID_COLOR, [0.99, 0.99, 0.99, 1]);

g.backgroundColor = myBrush;

win.alignChildren="row";

win.g10 = win.add('group');

win.g10.orientation = "row";

win.title = win.g10.add('statictext',undefined,'Copy Metadata');

win.title.alignment="bottom";

var g = win.title.graphics;

g.font = ScriptUI.newFont("Georgia","BOLDITALIC",22);

win.p1= win.add("panel", undefined, undefined, {borderStyle:"black"});

win.p1.alignChildren="fill";

var fileType = ["jpg","tif","psd","dng"];

win.g2 =win.p1.add('group');

win.g2.spacing=10;

win.g2.st1 = win.g2.add('statictext',undefined,'Source File Type');

win.g2.dd1 = win.g2.add('dropdownlist',undefined,fileType);

win.g2.dd1.selection=0;

win.g2.st2 = win.g2.add('statictext',undefined,'Destination File Type');

win.g2.dd2 = win.g2.add('dropdownlist',undefined,fileType);

win.g2.dd2.selection=1;

win.g3 =win.p1.add('group');

win.g3.spacing=10;

win.g3.cb1 = win.g3.add('checkbox',undefined,'Remove existing metadata');

win.g5 =win.p1.add('group');

win.g5.spacing=10;

win.g5.st1 = win.g5.add('statictext',undefined,'Source Files');

win.g5.st1.preferredSize=[100,20];

win.g5.et1 = win.g5.add('edittext');

win.g5.et1.preferredSize=[250,20];

win.g5.et1.enabled=false;

win.g5.bu1 = win.g5.add('button',undefined,'Browse');

win.g10 =win.p1.add('group');

win.g10.spacing=10;

win.g10.st1 = win.g10.add('statictext',undefined,'Destination Files');

win.g10.st1.preferredSize=[100,20];

win.g10.et1 = win.g10.add('edittext');

win.g10.et1.preferredSize=[250,20];

win.g10.et1.enabled=false;

win.g10.bu1 = win.g10.add('button',undefined,'Browse');

win.g15 =win.p1.add('group');

win.g15.orientation='row';

win.g15.alignment="top";

win.g15.spacing=10;

win.g15.bu1 = win.g15.add('button',undefined,'Process');

win.g15.bu1.preferredSize=[200,30];

win.g15.bu2 = win.g15.add('button',undefined,'Cancel');

win.g15.bu2.preferredSize=[200,30];

win.g5.bu1.onClick=function(){

     rawFolder = Folder.selectDialog("Please select the Source folder",app.document.presentationPath);

     if(rawFolder !=null){

        win.g5.et1.text =  decodeURI(rawFolder.fsName);

        }

}

win.g10.bu1.onClick=function(){

     destinationFolder = Folder.selectDialog("Please select the destination files folder",app.document.presentationPath);

     if(destinationFolder !=null){

        win.g10.et1.text =  decodeURI(destinationFolder.fsName);

        }

}

win.g15.bu1.onClick=function(){

    if(win.g5.et1.text == ''){

        alert("No Source folder selected!");

        return;

        }

    if(win.g10.et1.text == ''){

        alert("No Destination folder selected!");

        return;

        }

    if(win.g2.dd1.selection.index == win.g2.dd2.selection.index ){

        if(win.g5.et1.text == win.g5.et2.text){

            alert("You can not copy the same data to itself!");

            return;

            }

        }

    win.close(1);

    process(rawFolder,destinationFolder);

}

win.center();

win.show();

function process(rawFolder,destinationFolder){

var rawFiles = rawFolder.getFiles ("*."+win.g2.dd1.selection.text);

if(!rawFiles.length){alert("There are no source files to be processed!"); return;}

for (var a in rawFiles){

var Name = decodeURI(rawFiles.name).replace(/\.[^\.]+$/, '');

var destFile = File(destinationFolder + "/" + Name + "."+win.g2.dd2.selection.text);

if(destFile.exists) updateMetaData(rawFiles,destFile);

    }

}

function updateMetaData(sourceFile,destFile){

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

sourceFile = new Thumbnail(File(sourceFile));

destFile = new Thumbnail(File(destFile));

var md = sourceFile.synchronousMetadata;

var source = new XMPMeta( md.serialize() );

var md2 = destFile.synchronousMetadata;

var dest = new XMPMeta( md2.serialize() );

try{

if(win.g3.cb1.value){

XMPUtils.removeProperties(dest, XMPConst.NS_DC, "", XMPConst.REMOVE_ALL_PROPERTIES);  

XMPUtils.removeProperties(dest, XMPConst.NS_NS_XMP_RIGHTS, "", XMPConst.REMOVE_ALL_PROPERTIES);  

XMPUtils.removeProperties(dest, XMPConst.NS_NS_IPTC_CORE, "", XMPConst.REMOVE_ALL_PROPERTIES);  

XMPUtils.removeProperties(dest, XMPConst.NS_NS_PHOTOSHOP, "", XMPConst.REMOVE_ALL_PROPERTIES);  

}

copySchema( source, dest,XMPConst.NS_DC,[]);

copySchema( source, dest,XMPConst.NS_XMP_RIGHTS,[]);

copySchema( source, dest,XMPConst.NS_IPTC_CORE,[]);

copySchema( source, dest,XMPConst.NS_PHOTOSHOP,[]);

var updatedPacket = dest.serialize(XMPConst.SERIALIZE_OMIT_PACKET_WRAPPER | XMPConst.SERIALIZE_USE_COMPACT_FORMAT);

destFile.metadata = new Metadata(updatedPacket);

app.document.refresh();

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

}

function copySchema( source, dest, namespace, omitProps ) { 

    var propIter = source.iterator(XMPConst.ITERATOR_JUST_CHILDREN | XMPConst.ITERATOR_JUST_LEAF_NAME, namespace, "" );

    var prop = propIter.next();

    var prefix = XMPMeta.getNamespacePrefix( namespace );

    while(prop) {           

        var name = prop.path.substring( prefix.length );    

         if(omitProps != undefined) var copy = !contains( omitProps, name);

        if( copy ) {

            try{

            XMPUtils.duplicateSubtree( source, dest, namespace, prop.path,namespace, prop.path, 0 );       

            }catch(e){}

        }

        prop = propIter.next();

    }        

}

function contains( arr, member ){

    var r = false;

    for( var i = 0; i < arr.length &! r; ++i  ) {

        r = arr == member;

    }

    return r;

}

Votes

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
Advisor ,
Sep 05, 2013 Sep 05, 2013

Copy link to clipboard

Copied

Works faultlessly.

Very many thanks.

Votes

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
Advisor ,
Dec 02, 2013 Dec 02, 2013

Copy link to clipboard

Copied

Philip,

I have had great success with your scipt, but after all this time, I have just discovered another curiosity which I wonder are you able to address?

Your script works faultlessly, as I said, when copying keywords from source to destination provided that the source and destination are of different file types e.g. dng and jpg.

I haven't tested with every possible combination, but I have discovered that I can't copy when source and destination are the same file types e.g. jpg to jpg or dng to dng.

Many thanks

Votes

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 ,
Dec 02, 2013 Dec 02, 2013

Copy link to clipboard

Copied

Paul has done a version that you can select schemas and file types, so this might suit your needs.

See "Copy Metadata" in the Bridge section @ http://www.ps-bridge-scripts.talktalk.net/

Votes

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
Advisor ,
Dec 02, 2013 Dec 02, 2013

Copy link to clipboard

Copied

Hello,

I took a look at “Copy Metadata” but unfortunately it doesn’t accomplish what I wanted.

Can’t copy from one file to another with the same name and type, only different types. (You may wonder why I have identical files to copy between, but that is another story.)

Also “Copy Metadata” has no “dng” option in file types.

Thanks for your patience

Votes

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 ,
Dec 02, 2013 Dec 02, 2013

Copy link to clipboard

Copied

I have had a look at the code and it will let you copy to the same file type, also you can add dng to the fileType array in line 23, then it should do all you want Erik.

Votes

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
Advisor ,
Dec 03, 2013 Dec 03, 2013

Copy link to clipboard

Copied

Thanks for your advice.  Have managed to get everything working now.

In the line 23 you mention, I guess it will be ok to remove all the file types I never use to simplify the selection?

Votes

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