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.
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
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
Copy link to clipboard
Copied
Unfortunately, that solution appears not to apply to the Mac OS platform.
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
Copy link to clipboard
Copied
This thread may have the code you require?
Copy link to clipboard
Copied
This is not something I have done before, but I will attempt it this week. Thanks.
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;
}
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?
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.
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?
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
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?
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
Copy link to clipboard
Copied
Especially when you have thousands. Thanks again.
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?
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!
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;
}
}
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?
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;
}
}
Copy link to clipboard
Copied
Works faultlessly.
Very many thanks.
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
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/
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
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.
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?