Sync tags between files

This script merges the tags of the selected items (files and folders) in the source with those in the destination that have the same name. The tags will be unique, sorted alphabetically, and written to both files of a pair.

The script will work in collections, but not in Flatview.

In this published version, the script will only show the command it is going to run, but not execute it. Uncomment the last line in the script, to really modify the files.

Not sure what tags are?
https://www.gpsoft.com.au/help/opus12/index.html#!Documents/Keywords_for_SetAttr_META.htm

// https://resource.dopus.com/t/sync-tags-between-files/41616

// 2022-07-02

function OnClick(clickData) {
    var cmd = clickData.func.command;
    var tab = clickData.func.sourcetab;
    var dtab = clickData.func.desttab;
    var fsu = DOpus.FSUtil();
    var tagSet = DOpus.Create().StringSet();
    var tagVec = DOpus.Create().Vector();

    cmd.deselect = false;

    if (!dtab) return;

    cmd.RunCommand('Set UTILITY=otherlog');
    DOpus.ClearOutput();

    DOpus.Output('Enumerating...\n');

    for (var e = new Enumerator(tab.selected); !e.atEnd(); e.moveNext()) {
        var srcItem = e.item();
        if (srcItem.metadata == 'none') continue;

        var destItem = fsu.GetItem(fsu.Resolve(dtab.path + '\\' + srcItem.name));
        if (!fsu.Exists(destItem)) continue;
        if (destItem.metadata == 'none') continue;

        DOpus.Output(srcItem);
        DOpus.Output(destItem);

        tagVec.assign(srcItem.metadata.tags);
        tagVec.append(destItem.metadata.tags);
        tagVec.sort();
        tagSet.assign(tagVec); // remove duplicates

        var tagString = '';
        for (var ee = new Enumerator(tagSet); !ee.atEnd(); ee.moveNext()) {
            tagString += ee.item() + ';';
        }
        tagString = tagString.substring(0, tagString.length - 1);

        cmd.ClearFiles();
        cmd.AddFile(srcItem);
        cmd.AddFile(destItem);

        var cmdLine = ('SetAttr META "tags:' + tagString + '"');
        DOpus.Output(cmdLine);
        DOpus.Output('');
        // Un-comment the next line, if you think the script does the right thing
        // cmd.RunCommand(cmdLine);
    }

    DOpus.Output('\n... done.');
}
Button as XML
<?xml version="1.0"?>
<button backcol="none" display="both" label_pos="right" textcol="none">
	<label>SyncTags</label>
	<icon1>#properties</icon1>
	<function type="script">
		<instruction>@script JScript</instruction>
		<instruction>// https://resource.dopus.com/t/sync-tags-between-files/41616</instruction>
		<instruction />
		<instruction>// 2022-07-02</instruction>
		<instruction />
		<instruction>function OnClick(clickData) {</instruction>
		<instruction>    var cmd = clickData.func.command;</instruction>
		<instruction>    var tab = clickData.func.sourcetab;</instruction>
		<instruction>    var dtab = clickData.func.desttab;</instruction>
		<instruction>    var fsu = DOpus.FSUtil();</instruction>
		<instruction>    var tagSet = DOpus.Create().StringSet();</instruction>
		<instruction>    var tagVec = DOpus.Create().Vector();</instruction>
		<instruction />
		<instruction>    cmd.deselect = false;</instruction>
		<instruction />
		<instruction>    if (!dtab) return;</instruction>
		<instruction />
		<instruction>    cmd.RunCommand(&apos;Set UTILITY=otherlog&apos;);</instruction>
		<instruction>    DOpus.ClearOutput();</instruction>
		<instruction />
		<instruction>    DOpus.Output(&apos;Enumerating...\n&apos;);</instruction>
		<instruction />
		<instruction>    for (var e = new Enumerator(tab.selected); !e.atEnd(); e.moveNext()) {</instruction>
		<instruction>        var srcItem = e.item();</instruction>
		<instruction>        if (srcItem.metadata == &apos;none&apos;) continue;</instruction>
		<instruction />
		<instruction>        var destItem = fsu.GetItem(fsu.Resolve(dtab.path + &apos;\\&apos; + srcItem.name));</instruction>
		<instruction>        if (!fsu.Exists(destItem)) continue;</instruction>
		<instruction>        if (destItem.metadata == &apos;none&apos;) continue;</instruction>
		<instruction />
		<instruction>        DOpus.Output(srcItem);</instruction>
		<instruction>        DOpus.Output(destItem);</instruction>
		<instruction />
		<instruction>        tagVec.assign(srcItem.metadata.tags);</instruction>
		<instruction>        tagVec.append(destItem.metadata.tags);</instruction>
		<instruction>        tagVec.sort();</instruction>
		<instruction>        tagSet.assign(tagVec); // remove duplicates</instruction>
		<instruction />
		<instruction>        var tagString = &apos;&apos;;</instruction>
		<instruction>        for (var ee = new Enumerator(tagSet); !ee.atEnd(); ee.moveNext()) {</instruction>
		<instruction>            tagString += ee.item() + &apos;;&apos;;</instruction>
		<instruction>        }</instruction>
		<instruction>        tagString = tagString.substring(0, tagString.length - 1);</instruction>
		<instruction />
		<instruction>        cmd.ClearFiles();</instruction>
		<instruction>        cmd.AddFile(srcItem);</instruction>
		<instruction>        cmd.AddFile(destItem);</instruction>
		<instruction />
		<instruction>        var cmdLine = (&apos;SetAttr META &quot;tags:&apos; + tagString + &apos;&quot;&apos;);</instruction>
		<instruction>        DOpus.Output(cmdLine);</instruction>
		<instruction>        DOpus.Output(&apos;&apos;);</instruction>
		<instruction>        // Un-comment the next line, if you think the script does the right thing</instruction>
		<instruction>        // cmd.RunCommand(cmdLine);</instruction>
		<instruction>    }</instruction>
		<instruction />
		<instruction>    DOpus.Output(&apos;\n... done.&apos;);</instruction>
		<instruction>}</instruction>
	</function>
</button>

4 Likes

This looks great! If I can get it to work, it will be very useful to me. I am trying to figure out scripts and JavaScript. I had to research how to 'uncomment' the JavaScript.
Could this be edited to sync other metadata such as Title, Description, Rating, and GPS coordinates?
I am a professional photo organizer, and a huge task in all my digital projects is duplicate removal. A big challenge when de-duping is that one file in a duplicate group may be desirable to keep because it has larger pixel dimension, but another file has added metadata that needs to be preserved. Syncing the metadata would make de-duping much easier.

Yes, you can! Just remove the two leading slashes.

image

Yes. Would be rather copying than syncing, I guess? Or do you want to merge text entries? Averaging ratings would not be overly useful, I presume?

Thank you. I used the word 'sync' because this is about 'syncing' tags.

In most cases, I get files with no Tags, Title (Object), Description, Rating, or other, AND duplicate files that do have metadata in those fields.

Because I gather my clients' files from so many different Sources (EHDs, Google Photos, Apple Photos Libraries, Dropbox or other cloud storage, file system on Mac and/or PC) many of those Sources contain duplicate files and even entire duplicate folders, but not all will have had metadata added. Unfortunately, the 'best' files are not always the ones with the added metadata.

So, I would like to copy metadata from files that have metadata in those fields to files that don't have metadata in those fields.

I realize the files must have the same name, and that's no problem, as I can make them the same if they aren't.

In some cases files may have different Keywords (Tags), in which case I would love to be able to sync (or merge) them so that each file acquires the Tag(s) of the other file.

Ratings are not usually a factor, I'm not too concerned about that field.

So, since you say this will work with other metadata such as Title, Description, Rating, and GPS coordinates, please help me do that.
I think I need to determine the SetAttr META Keywords for those fields, but I don't know how/where I would add them to the script because I don't know JavaScript.
Can you please advise?

Alright, so no answers or suggestions?
I intend to figure out how to edit this to suit my needs, but can someone please tell me if I can add lines to the script for each metadata field I want to sync/copy, or if I'd need to create a script for each field?

Either way is possible. It's entirely up to you and how you want the script to work. But if you don't know JavaScript, editing the script will be difficult. Learning the basics first would be the right first step. There are loads of tutorials for learning JavaScript on the web.

The SetAttr META keywords are in the manual.

I said I had to research how to 'uncomment', but I neglected to say that I found the answer quickly. But thank you for your willingness to help.