How to Combine Two Separate Shell Outputs to a CSV File?

I am trying to create a csv file that contains all of the files in the directory and their tags.

While I am aware of the command line tool Tag, it isn't a solution for me as I intend to use this macro on several machines and installing tag on all of them becomes cumbersome and difficult.

Using these two macros gets me really close:

Create tag csv generates me a file that contains tags in this format
Red, Orange

and Create Folder csv generates me a file that contains the ls output in this format:


My end goal is to export a table in this format:
Screen Shot 2022-10-19 at 9.01.57 AM

This script is going to run periodically so that I can track the contents of a various directories, their tags, and create csv outputs that represents their contents/tags which I will link to in a master excel document

Any ideas on how I can move forward is much appreciated!

I always worry about listing a directory twice, at different times, and hoping you'll get the same result.

Since you are running a shell action for each item in the collection anyway, either get the folder name with a KM action (eg "Split Path") or do the whole lot in the shell script.

You're passing in a path, and the Unix-y way of getting the last part of the path is basename. You can combine that output with tab character (which saves you having to meet around with commas in the text), add the output from mdls and finish it all off with a newline character.

Easiest way to clean the mdls output is to delete the ()\n characters :wink: Obviously that won't work well if you have brackets and/or spaces in your tags, in which case you'll have to rethink (and will probably find it easier to do the processing in with KM actions).

Putting the above together gives us

echo -en $( basename "$KMVAR_Folder" )"\t";
mdls -raw -name kMDItemUserTags "$KMVAR_Folder" | tr -d "()\n ";

Different echos behave differently, so we've invoked bash. And remember that, by default, the "Shell Script" action removes any trailing newlines -- we want one, so turn that off in the action's "Settings" cogwheel.

Here's a demo, using local variables instead of the globals you had above:

Gather Names and Tags.kmmacros (3.9 KB)


This worked perfectly! Thank you so much!

Can you please help me understand the syntax:

It would be great to understand the entire process so I can implement elsewhere moving forward.

Thank you!!

The pipe | redirects the output of the mdls command to be the standard input of tr.

You can find out about tr ("translate") using man tr in the Terminal (or by Googling the same). Usually it's used to swap characters in a string -- take standard input and any character in the first list is swapped for the corresponding one in the second, then output the new string. But the -d flag means "delete any and all characters in the following list" (and you only supply one list).

The list of characters to delete is between the double-quotes -- ( and ) are obvious, the last character is a typed space , and \n is the Unix new-line.

So "delete all the parentheses, spaces, and new-lines from the output of mdls and return the resulting string".