When searching for files with Spotlight on macOS, the search index respects certain metadata fields assosiated with the file. This metadata can be used to improve search results and to provide additional information about the file. In this post, I’ll show you how to write this metadata to a file using Objective-C.
The metadata that Spotlight uses to index files is stored as extended file attributes. These attributes are key-value pairs that are stored in the file system and can be accessed using the xattr
command-line tool. The xattr
tool can be used to list, read, and write extended attributes.
To list the extended attributes of a file, use the following command:
xattr -l file.txt
Spotlight uses several different attributes to enrich its search index, such as com.apple.metadata:kMDItemWhereFroms
and com.apple.metadata:kMDItemDownloadedDate
. These attributes are used to store information about the file’s origin and download date, respectively. In this article, we will write the com.apple.metadata:kMDItemDescription
attribute to a file (see documentation).
To write extended file attributes in Objective-C, we can use the setxattr
function from the sys/xattr.h
header file. This function takes the path to the file, the name of the attribute, a pointer to the value, the size of the value, and a set of options as arguments.
The following code snippet demonstrates how to write the com.apple.metadata:kMDItemDescription
attribute to a file. First, we define the file path and the description that we want to write to the file. Then, we convert the description to a C string and call the setxattr
function to write the attribute to the file. For these metadata attributes, the value is a binary plist, so you need to convert the description to a binary plist before writing it to the file.
#import <Foundation/Foundation.h>
#include <sys/xattr.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString *filePath = @"/path/to/file.txt";
NSString *description = @"This is a description of the file";
const char *attributeName = "com.apple.metadata:kMDItemDescription";
// convert value to binary plist
NSData *value = [NSPropertyListSerialization dataWithPropertyList:description
format:NSPropertyListBinaryFormat_v1_0
options:0
error:nil];
size_t size = value.length;
// do not follow symbolic links, create or replace the attribute
int options = XATTR_NOFOLLOW | 0;
int result = setxattr(filePath.fileSystemRepresentation, attributeName, value.bytes, size, 0, options);
if (result == 0) {
NSLog(@"Successfully wrote extended attribute");
} else {
NSLog(@"Failed to write extended attribute");
}
}
return 0;
}
This way, you can write extended file attributes to a file using Objective-C. The setxattr
function returns 0 on success and -1 on failure, so you can use this to check if the attribute was written successfully.
To validate that the attribute was written to the file, you can use the xattr
command-line tool again to list the specific extended attribute:
xattr -p com.apple.metadata:kMDItemDescription file.txt