fox-hamachi
fox-hamachi

Reputation: 31

Unable to set MacOS Finder Comment Metadata using xattr in Python

Having a file-specific comment visble in the finder is desirable as part of a larger Python project. So, I'm trying to set the finder comment for 4500 files with Python 3.8.2 running on Big Sur. I've achieved this using the osxmetadata package, but it takes 2-3 minutes, assumedly because of the calls to AppleScript.

Can Python alone make finder comments stick, and if so how? Or, if you have to reach outside Python, are there more efficient methods than running an Applescript 4500 times?

Using xattr doesn't do the trick. The code below successfully sets the extended attribute to the same value as Get Info or osxmetadata. But the string/comment is not reflected in the finder.

import xattr
import plistlib
from plistlib import FMT_BINARY

file = 'test.json'
bplist = plistlib.dumps('Hello World', fmt=FMT_BINARY)

xattr.setxattr(file, 'com.apple.metadata:kMDItemFinderComment', bplist)

The result in Terminal:

% xattr -pl com.apple.metadata:kMDItemFinderComment test.json
0000   62 70 6C 69 73 74 30 30 5B 48 65 6C 6C 6F 20 57    bplist00[Hello W
0010   6F 72 6C 64 08 00 00 00 00 00 00 01 01 00 00 00    orld............
0020   00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00    ................
0030   00 00 00 00 14                                     .....

Some more investigation shows the directory's .DS_Store file doesn't change. So, I think I'm only changing the "spotlight comment" and not the "finder comment" (?). I thought about just writing a new .DS_Store file for my various directories, but it doesn't seem possible.

Any thoughts about Python or hybrid solutions to the question would be appreciated. Thanks!

Upvotes: 3

Views: 686

Answers (1)

Mark Setchell
Mark Setchell

Reputation: 207405

I did some experiments and it seems there is quite considerable overhead in calling osascript, so it would be best to avoid calling it once per file for each of your 4,000 files.

I found the following runs in 7 seconds for 1000 files called f-1, f-2 and so on:

#!/bin/bash

osascript <<EOF
repeat with i from 1 to 1000
    set fName to "/Users/mark/f-" & i as string
    set fName to (fName as POSIX file)
    tell application "Finder" to set comment of item fName to "Freddy frog"
end repeat
EOF

Whereas if you create a fresh osascript per file like this, it takes over 2 minutes:

# This takes over 2 minutes with 1000 files
for f in f* ; do
filename=$(realpath "$f")
osascript <<EOF
tell application "Finder" to set comment of item POSIX file "$filename" to "Filename=$filename"
EOF
done

If your filenames aren't sequentially ordered like that, you could maybe make a list along these lines, or read the filenames from a file you create elsewhere in your app:

osascript <<EOF
set filelist to {"f-1", "f-2", "f-3"}
repeat with f in filelist
    set fName to "/Users/mark/" & f
    set fName to (fName as POSIX file)
    tell application "Finder" to set comment of item fName to "Freddy frog"
end repeat
EOF
exit

Upvotes: 2

Related Questions