Sync labels between files

This script merges the labels of the selected items (files and folders) in the source with those in the destination that have the same name. Only explicitly set labels will be processed. Labels set via wildcard and label filters will be ignored. The labels will be written to both files of a pair.

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

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

// https://resource.dopus.com/t/sync-labels-between-files/42543

// 2022-10-21

function OnClick(clickData) {
    var cmd = clickData.func.command;
    var tab = clickData.func.sourcetab;
    var dtab = clickData.func.desttab;
    var fsu = DOpus.FSUtil();
    var labelVec = 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();

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

        labelVec.assign(srcItem.Labels('', 'explicit')); // use Labels(), if you want to 
        labelVec.append(dstItem.Labels('', 'explicit')); // include labels from label filters
        labelVec.sort();
        labelVec.unique();

        if (labelVec.count == 0) continue;

        var labelString = '';
        for (var ee = new Enumerator(labelVec); !ee.atEnd(); ee.moveNext()) {
            labelString += ee.item() + ',';
        }
        labelString = labelString.slice(0, -1);

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

        var cmdLine = ('Properties SETLABEL="' + labelString + '"');
        DOpus.Output(srcItem);
        DOpus.Output(dstItem);
        DOpus.Output(cmdLine);
        DOpus.Output('');
        cmd.RunCommand(cmdLine);
    }

    DOpus.Output('\n... done.');
}
Button as XML
<?xml version="1.0"?>
<button backcol="none" display="both" label_pos="right" separate="yes" textcol="none">
	<label>SyncLabels</label>
	<icon1>#properties</icon1>
	<function type="script">
		<instruction>@script JScript</instruction>
		<instruction>// https://resource.dopus.com/t/sync-labels-between-files/42543</instruction>
		<instruction />
		<instruction>// 2022-10-21</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 labelVec = 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 />
		<instruction>        var dstItem = fsu.GetItem(fsu.Resolve(dtab.path + &apos;\\&apos; + srcItem.name));</instruction>
		<instruction>        if (!fsu.Exists(dstItem)) continue;</instruction>
		<instruction />
		<instruction>        labelVec.assign(srcItem.Labels(&apos;&apos;, &apos;explicit&apos;)); // use Labels(), if you want to </instruction>
		<instruction>        labelVec.append(dstItem.Labels(&apos;&apos;, &apos;explicit&apos;)); // include labels from label filters</instruction>
		<instruction>        labelVec.sort();</instruction>
		<instruction>        labelVec.unique();</instruction>
		<instruction />
		<instruction>        if (labelVec.count == 0) continue;</instruction>
		<instruction />
		<instruction>        var labelString = &apos;&apos;;</instruction>
		<instruction>        for (var ee = new Enumerator(labelVec); !ee.atEnd(); ee.moveNext()) {</instruction>
		<instruction>            labelString += ee.item() + &apos;,&apos;;</instruction>
		<instruction>        }</instruction>
		<instruction>        labelString = labelString.slice(0, -1);</instruction>
		<instruction />
		<instruction>        cmd.ClearFiles();</instruction>
		<instruction>        cmd.AddFile(srcItem);</instruction>
		<instruction>        cmd.AddFile(dstItem);</instruction>
		<instruction />
		<instruction>        var cmdLine = (&apos;Properties SETLABEL=&quot;&apos; + labelString + &apos;&quot;&apos;);</instruction>
		<instruction>        DOpus.Output(srcItem);</instruction>
		<instruction>        DOpus.Output(dstItem);</instruction>
		<instruction>        DOpus.Output(cmdLine);</instruction>
		<instruction>        DOpus.Output(&apos;&apos;);</instruction>
		<instruction>        cmd.RunCommand(cmdLine);</instruction>
		<instruction>    }</instruction>
		<instruction />
		<instruction>    DOpus.Output(&apos;\n... done.&apos;);</instruction>
		<instruction>}</instruction>
	</function>
</button>

6 Likes

It's been a while since I've had to edit code so I'd like to doublecheck here that this would be theoretically possible.

Could this also handle subfolders if we added a recursive version of the function to it? As long as it checked to make sure that the folder existed in both the source and destination, I don't think it would cause any issues.

Yes, this script can be adapted in many directions. Let it loop through subfolders, use other criteria than "same name" to pick sync pairs, sync the labels from more than two files, change the labels before writing them back... whatever you need.

1 Like