While working on photos, I wanted to programmatically add tags to photos. The tags would be read from a file.
I formally used Finder to do this, but it can be tedious for a large universe of tags and there's no record of the association.
Here's my solution which is really awkward and brittle. Surely there is a better way. Please add your comments on that way. Until then, I'll use this code.
using System;
using System.Diagnostics;
namespace ImageDescriptions
{
public class Utilities
{
public static string? executeShellCommand(string scriptFile, string arguments)
{
var processInfo = new ProcessStartInfo()
{
FileName = scriptFile,
Arguments = arguments,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};
string? result = string.Empty;
Process process = Process.Start(processInfo); // Start that process.
while (!process.StandardOutput.EndOfStream)
{
result = process.StandardOutput.ReadLine();
System.Console.WriteLine("result: " + result);
}
process.WaitForExit();
return result;
}
///
/// Sets tags on a file in OS X.
/// This is really awkward and brittle.
///
/// Comma separated list, e.g., "red,black,green"
/// file to which we add tags
public static void SetTags(string? tagCsv, string filename)
{
System.Console.WriteLine($"SetTags: '{tagCsv}', '{filename}'");
var tagXmlString = string.Empty;
if (tagCsv == null || String.IsNullOrWhiteSpace(tagCsv)) { return; }
var tags = tagCsv.Split(',');
foreach (var tag in tags)
{
tagXmlString += "" + tag.Trim() + "";
}
var scriptFile = "/usr/bin/xattr";
var arguments = " -w"
+ " com.apple.metadata:_kMDItemUserTags"
+ @" """
+ @" "
+ tagXmlString
+ @" """
+ " " + filename;
System.Console.WriteLine($"executeShellCommand: {scriptFile}, {arguments}");
Utilities.executeShellCommand(scriptFile, arguments);
}
}
}
Here's a program that reads a data file and then calls "SetTags()":
using ImageDescriptions;
public class ImageDescription
{
public static void Main(string[] args)
{
if(args.Length < 1)
{
Console.WriteLine("usage: ImageDescription ");
Environment.Exit(1);
}
string filename = args[0];
FileStream file = File.OpenRead(filename);
var lines = File.ReadLines(filename);
foreach (var line in lines)
{
Description description = new Description(line);
Console.WriteLine(line);
Console.WriteLine(description);
Utilities.SetTags(description.tags, description.name);
}
}
}
A line from the data file looks like this:
2013-01-23-0702-IMG_8252.jpg "Dessert pie with fruit -tags:dessert,fruit,healthy,pie"