How to Access Folder Tags from an External Script

I've been struggling with finding a way to read Folder Tags from an external script. I want to use this data so I can trigger automated tasks in other systems when a folder is discovered with specific tags. I am using PowerShell, although I am not tied to it.

I know the folder tags are stored in the OpusMetaInformation Alternate Data Stream, but the various native command line tools struggle reading it. I am able to see the stream in some UI based tools, but that does not help me for scripting. I was able to use DOpusRT.exe to write the tags, which is nice, however I could not find a way to read the tags using that tool.

This forum thread is very helpful, but I was not able to translate the provided details into usable code:

It seems the original poster was hitting the same problem trying to read the values in PowerShell and ended up settling on a script triggered from within Directory Opus.

Next I am going to look into creating a custom internal DO command that I can hopefully call externally from DOpusRT.exe, but I have spent countless hours going down various dead ends and before I go down this next path I am hoping to see if others here have a solution to this problem already, or have advice on a better approach.

1 Like

I never managed to read OpusMetaInformation with Opus' own tools.

That should work well.

I ended up using the following approach. This is my first time scripting with DOpus, so there might be a better way. I would not consider this "Production Ready" in any sense, but it works for my needs and others may get some use out of it, or at least it provides a starting point.

The DOpus script

// ExportTags.js
// NathanN 2024

function OnInit(initData) {
    initData.name = "Export Tags";
    initData.desc = "Creates an internal ExportTags command to export file and Folder tags to a separate file, for use with external scripts.";
    initData.default_enable = true;
    var cmd = initData.AddCommand();
    cmd.name = "ExportTags";
    cmd.method = "OnExportTags";
    cmd.desc = initData.desc;
    cmd.label = "Export Tags";
    cmd.template = "FILE,EXPORTFILE/O";
}

function OnExportTags(scriptCmdData) {

    ExportFile = "C:\\DOpusTagExport.txt"; //default location to save file when one is not passed in the ExportFile argument.
    if ( scriptCmdData.func.args.got_arg.exportfile ) ExportFile = scriptCmdData.func.args.exportfile;

	var sourceFile = DOpus.FSUtil.GetItem(scriptCmdData.func.args.file)

	// Get Tags from source file/folder
	var ItemTags = sourceFile.metadata.tags;

	// Flatten ItemTags array in preparation for single line file output
	var tagList = "";
	for ( i = 0; i < ItemTags.count; i++ ) { tagList += ItemTags(i) + "; " };
	
	//Optionally Output to script logs for troubleshooting.
	//DOpus.Output(tagList);
	
	//Open file for reading and writing.
	ExportFileObj = DOpus.FSUtil.OpenFile(ExportFile, "rwo");

	// Reads current file contents.
	// This also moves the file pointer to the end of the file before writing.
	// If the preference is to overwrite then this, along with the file open method can be modified.
	// Alternatively, the external script can delete the file before calling this Opus command.
	var stt = DOpus.Create().StringTools();
	CurrentFileContents = stt.Decode(ExportFileObj.Read(), 'utf8');

	// This next line can be modified for the preferred output string
	var FinalOutput = sourceFile + ": " + tagList + "\n" 
	
	ExportFileObj.Write(FinalOutput)
	ExportFileObj.close
}

Here is an example PowerShell script that pulls the tags from the produced export file into an array.
It accepts 2 parameters, the first being the target file/folder to pull tags from.
The second being the Export File path. The Export path defaults to the root of the C: drive if not otherwise specified.
There is a 3rd parameter to set the location of dopusrt.exe, but that should only need to get set once.

# getTags.ps1
# NathanN (2024)
#
# Gets File and Folder tags from any file or folder.
# Returns an array of tags.
#
# Expects Opus Export file to produce lines in this format:
# <TargetFile>: <Tag1>; <Tag2>; <Tag3>; ...
# 
# Depends on ExportTags.js to be imported into Directory Opus

Param (
    $TargetFile,
    $ExportFile = "C:\DOpusTagExport.txt",
    $DOpusRT = "C:\Program Files\GPSoftware\Directory Opus\dopusrt.exe"
    )

# Optionally delete the Export file (if it exists) so we have a clean lookup
if (Test-Path -Path $ExportFile) {Remove-Item $ExportFile}

# Trigger DOpus command
& $DOpusRT /acmd ExportTags File $TargetFile ExportFile $ExportFile

# This block attempts to find tags in the export file based on Target File path (for up to 10 seconds).
# This is needed since it's unknown how long DO will take to output the results.
# If the path already exists in the file then this can lead to stale matches.
# Deleting the file prior to the check insures we have only one hit.
$Match = ""
while (!$Match) {
    if (Test-Path -Path $ExportFile) {
        $Match = Get-Content $ExportFile | Where-Object { $_.StartsWith($TargetFile + ':') } | Select-Object -Last 1

        #Break out of while loop when we find what we need
        if ($Match){Break}
    }

    # Wait half second before next try
    Start-Sleep .5
}

# Return an array of tags
$Tags = $Match.Split(':')[2].Split(";").Trim()

Return $Tags

For immediate output this PowerShell script can be ran as-is, but it's probably better to put into a variable as in this example:

$MyTags = .\getTags.ps1 "D:\People\testfolder\NewTextDocument.txt"
Then you can read using the array syntax: $MyTags[0]