How can I edit file metadata in OS X?
Does anyone know if it is possible to directly edit file metadata on OS X. Specifically in perl. The parameter I'm specifically trying to change is kMDItemFSLabel
(The color of the file). I've had a search around and I can't seem开发者_如何学JAVA to find a way to do this without using a module such as Mac::Glue or an external application (Finder).
The kMDItemFSLabel
attribute is a property of the Finder. You need to use a way to communicate with the Finder to change its data. As far as I know, there is no bit you can twiddle with Perl to change the Finder's data without going through the Finder.
There are several ways to do this:
Use CamelBones when the new version comes out. That allows a bridge to Objective C from Perl. Then you will need to use the Apple method with Cocoa system calls. Steep learning curve for Cocoa...
If you have developer tools, use /Developer/Tools/SetFile (if that supports the metadata item)
Use osascript to send the message to the Finder to change the color of the file. You can look at this earlier SO post for hints on doing that.
Most of the Perl related Objective C / Cocoa bridges have died unfortunately. MacPerl has not been updated since 2005.
Almost all the easiest methods require knowing at least minimal amount of Applescript and calling the text of that script though an interpolated type call to osascript.
In its 1 line form, osascript makes Perl look beautiful:
osascript -e 'tell application "Finder"' -e "activate" -e "display dialog \"hello\"" -e 'end tell'
To use osascript from Perl, most use a HERE document. There are examples from I book I have called Applescript - The Definitive Guide and from brian d foy on Controlling iTunes with Perl.
Here is a script in Perl I wrote for setting file color using osascript:
#!/usr/bin/perl
use strict; use warnings;
use File::Spec;
use String::ShellQuote;
sub osahere {
my $rtr;
my $scr='osascript -ss -e '."'".join ('',@_)."'";
open my $fh, '-|', $scr or die "death on osascript $!";
$rtr=do { local $/; <$fh> };
close $fh or die "death on osascript $!";
return $rtr;
}
sub set_file_color {
# -- No color = 0
# -- Orange = 1
# -- Red = 2
# -- Yellow = 3
# -- Blue = 4
# -- Purple = 5
# -- Green = 6
# -- Gray = 7
my $file=shift;
my $color=shift || 0;
$color=0 if $color<0;
$color=7 if $color>7;
$file=File::Spec->rel2abs($file)
unless File::Spec->file_name_is_absolute( $file );
$file=shell_quote($file);
return undef unless -e $file;
my $rtr=osahere <<"END_SET_COLOR" ;
tell application "Finder"
set f to "$file"
set ItemToLabel to POSIX file f as alias
set the label index of ItemToLabel to $color
end tell
END_SET_COLOR
return $rtr;
}
set_file_color("2591.txt",2);
If the Finder color is 0, kMDItemFSLabel
is 0. If there is any color set, kMDItemFSLabel
becomes 8-color. ie, label "orange" is label index
1, kMDItemFSLabel
= 7; label "red" is label index
2, kMDItemFSLabel
= 6; and so on.
There is no built-in function in Perl to operate on Mac filesystem metadata. Either your use a library from CPAN, or write it yourself, probably not as well as the author of the one in CPAN did.
It is actually not that complicated to implement. You can use the xattr
command as shown in the doc string below...
I've wrapped the basic function in a python script which applies named colors to a series of files...
#!/usr/bin/env python
"""
==================================
LABELCOLOR.PY - Colorize Finder labels of files
Usage:
labelcolor.py [color] *.jpg
where color is a name or abbreviation as defined below:
clear (c), gray (a), green (g), purple (p),
blue (b), yellow (y), red (r), orange (o)
The shell command used is:
xattr -wx com.apple.FinderInfo \
0000000000000000000400000000000000000000000000000000000000000000 myfile.txt
where 04 in the middle of the zeroes is the color definition
==================================
"""
import sys
import os
import subprocess
def colorizeFile(ColorName,FileName):
ReverseTable = {
"clear" : "01",
"gray" : "03",
"green" : "04",
"purple" : "06",
"blue" : "09",
"yellow" : "0A",
"red" : "0C",
"orange" : "0E",
"c" : "01",
"a" : "03",
"g" : "04",
"p" : "06",
"b" : "09",
"y" : "0A",
"r" : "0C",
"o" : "0E",
}
HexString = 18*"0" + ReverseTable.get(ColorName) + 44*"0"
Xcommand = 'xattr -wx com.apple.FinderInfo {0} {1}'.format(HexString,FileName)
ProcString = subprocess.check_call(Xcommand, stderr=subprocess.STDOUT,shell=True)
if __name__ == "__main__":
if len(sys.argv)<3:
sys.stderr.write(__doc__.format(sys.argv[0]))
else:
Cname = sys.argv[1]
Flist = sys.argv[2:]
for File in Flist:
colorizeFile(Cname.lower(),File)
sys.stderr.write("## Colorized {0} file(s) as {1}\n".format(len(Flist),Cname))
This question and answered a long time ago. Since then, the world has evolved:
The tag project is a binary that allows you to manipulate tags (formerly called labels).
xattr lets you get and set all sorts of things. This is what I mainly use. For example, with Mojolicious I like to add
com.apple.metadata:kMDItemWhereFroms
to things I download.
精彩评论