macos cocoa metadata command-line-tool

macos - ¿Cómo puedo agregar "etiquetas" de OS X a los archivos mediante programación?



cocoa metadata (10)

Desde Mavericks, OS X ha tenido la capacidad de etiquetar y colorear archivos en el Finder.

¿Hay alguna forma de agregar etiquetas a los archivos a través de las API de Cocoa o mediante un comando de shell?


En preguntar diferente

Con respuestas múltiples, una de las cuales es accepted :

Aquí en , la pregunta surgió un poco antes (2013-11-01), así que agregaré mi respuesta aquí.

openmeta

Código abierto en https://code.google.com/p/openmeta/source/browse/trunk/trunk/openmeta

El comando openmeta parece tener un enfoque de doble atributo, trabajando con ambos:

  • com.apple.metadata:kMDItemOMUserTags
  • com.apple.metadata:_kMDItemUserTags

Ejemplo de uso

sh-3.2$ sw_vers ProductName: Mac OS X ProductVersion: 10.9.5 BuildVersion: 13F1096 sh-3.2$ uname -a Darwin gpes3e-gjp4.local 13.4.0 Darwin Kernel Version 13.4.0: Wed Mar 18 16:20:14 PDT 2015; root:xnu-2422.115.14~1/RELEASE_X86_64 x86_64 sh-3.2$ date Sun 26 Jul 2015 08:00:23 BST sh-3.2$ rm ~/Desktop/test.txt sh-3.2$ touch ~/Desktop/test.txt sh-3.2$ xattr -l ~/Desktop/test.txt sh-3.2$ ./openmeta openmeta version 0.1 by Tom Andersen code.google.com/p/openmeta/ Usage: openmeta [options] -p PATH[s] Note that commas are to be used nowhere - tag lists use quotes for two word tags in output example (list tags and ratings): openmeta -p PATH example (list tags and ratings multiple): openmeta -p PATH PATH example (list tags): openmeta -t -p PATH[s] example (add tags): openmeta -a foo bar -p PATH[s] example (add tags with spaces): openmeta -a "three word tag" "foo bar" -p PATH[s] example (set tags): openmeta -s foo bar -p PATH[s] example (clear all tags): openmeta -s -p PATH[s] example (set managed): openmeta -m Y -p PATH[s] example (set rating 0 - 5 stars): openmeta -r 3.5 -p PATH[s] example (print rating): openmeta -r -p PATH[s] example (clear rating): openmeta -r 0.0 -p PATH[s] example (lousy rating): openmeta -r 0.1 -p PATH[s] sh-3.2$ ./openmeta -a kerfuffle -p ~/Desktop/test.txt kerfuffle /Users/gjp22/Desktop/test.txt sh-3.2$ ./openmeta -p ~/Desktop/test.txt /Users/gjp22/Desktop/test.txt tags: kerfuffle rating: none found sh-3.2$ xattr -l ~/Desktop/test.txt com.apple.metadata:kMDItemOMUserTagTime: 00000000 62 70 6C 69 73 74 30 30 33 41 BB 64 BD 3C D4 95 |bplist003A.d.<..| 00000010 F2 08 00 00 00 00 00 00 01 01 00 00 00 00 00 00 |................| 00000020 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000030 00 11 |..| 00000032 com.apple.metadata:kMDItemOMUserTags: 00000000 62 70 6C 69 73 74 30 30 A1 01 59 6B 65 72 66 75 |bplist00..Ykerfu| 00000010 66 66 6C 65 08 0A 00 00 00 00 00 00 01 01 00 00 |ffle............| 00000020 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 |................| 00000030 00 00 00 00 00 14 |......| 00000036 com.apple.metadata:_kMDItemUserTags: 00000000 62 70 6C 69 73 74 30 30 A1 01 5B 6B 65 72 66 75 |bplist00..[kerfu| 00000010 66 66 6C 65 0A 30 08 0A 00 00 00 00 00 00 01 01 |ffle.0..........| 00000020 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 |................| 00000030 00 00 00 00 00 00 00 16 |........| 00000038 kOM109SyncDone: 00000000 62 70 6C 69 73 74 30 30 09 08 00 00 00 00 00 00 |bplist00........| 00000010 01 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 09 |..........| 0000002a sh-3.2$

Limitaciones de otras utilidades.

Apple Finder, por ejemplo.

Después de usar el Finder para eliminar la etiqueta kerfuffle , kerfuffle permanece como una etiqueta OpenMeta:

sh-3.2$ date ; xattr -l ~/Desktop/test.txt Sun 26 Jul 2015 08:02:13 BST com.apple.metadata:kMDItemOMUserTagTime: 00000000 62 70 6C 69 73 74 30 30 33 41 BB 64 BD 3C D4 95 |bplist003A.d.<..| 00000010 F2 08 00 00 00 00 00 00 01 01 00 00 00 00 00 00 |................| 00000020 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000030 00 11 |..| 00000032 com.apple.metadata:kMDItemOMUserTags: 00000000 62 70 6C 69 73 74 30 30 A1 01 59 6B 65 72 66 75 |bplist00..Ykerfu| 00000010 66 66 6C 65 08 0A 00 00 00 00 00 00 01 01 00 00 |ffle............| 00000020 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 |................| 00000030 00 00 00 00 00 14 |......| 00000036 com.apple.metadata:_kMDItemUserTags: 00000000 62 70 6C 69 73 74 30 30 A0 08 00 00 00 00 00 00 |bplist00........| 00000010 01 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 09 |..........| 0000002a kOM109SyncDone: 00000000 62 70 6C 69 73 74 30 30 09 08 00 00 00 00 00 00 |bplist00........| 00000010 01 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 09 |..........| 0000002a sh-3.2$

Entendiendo esas limitaciones

Con atención a los dominios y las convenciones de nomenclatura: los pensamientos de los desarrolladores sobre la adopción de OpenMeta - Ironic Software (2009-03, y ahora en Internet Archive Wayback Machine) nos recuerdan que com.apple.metadata era para el uso de Apple cuando OpenMeta (un proyecto que no está en el dominio apple.com ) comenzó el enfoque com.apple.metadata:kMDItemOMUserTags orientado a Apple.

Por lo tanto, no debería esperar que el software de Apple obtenga o mantenga la compatibilidad con ambos enfoques de etiquetado.

Casos de borde

En algunos casos, puede ser conveniente eliminar las etiquetas de Apple orientadas a com.apple.metadata:_kMDItemUserTags sin eliminar las etiquetas de OpenMeta orientadas a com.apple.metadata:kMDItemOMUserTags .

Sin embargo, hacerlo de manera programática probablemente esté fuera del alcance de la pregunta formulada por @nacross.


Agrego esta respuesta, porque OP pidió un script de shell y lo etiquetó bash . Escribí este servicio de Automator, que etiqueta el archivo seleccionado con las etiquetas de otro archivo. He añadido comentarios para describir el uso de la interacción de bash con las etiquetas y los colores utilizando el script de bash.

Lo esencial

En los scripts, se puede acceder a las etiquetas de OpenMeta y Mavericks con el comando xattr . Usándolo sin modificadores, $ xattr [file] , proporciona una lista de atributos establecidos. $ xattr -h da una buena guía de uso.

Las etiquetas de Mavericks están en com.apple.metadata: _kMDItemUserTags, mientras que las etiquetas de OpenMeta pueden estar en una variedad de atributos. Entre otros com.apple.metadata:kOMUserTags , org.openmetainfo:kMDItemOMUserTags y org.openmetainfo:kOMUserTags .

Mavericks maneja los colores y las etiquetas en diferentes atributos, colocando etiquetas en _kMDItemUserTags y colores en FinderInfo para cada archivo. Esta es una elección extraña, y es una de las razones por las que Finder tiene problemas bajo la presión de etiquetar. Si tiene 800 archivos etiquetados como kapow , cada uno en una carpeta diferente, y posteriormente elige el color azul para kapow , Finder tiene que encontrar y modificar los atributos de cada archivo.

Puede jugar con la rareza eliminando el atributo com.apple.FinderInfo de un archivo etiquetado y coloreado: $ xattr -d com.apple.FinderInfo [file] . El color desaparecerá en las listas del Finder, pero la etiqueta (y su color) permanecerán asociadas al archivo.

Bash script para importar etiquetas de otro archivo

En el script, los archivos seleccionados en Finder se guardan en la variable $ tagless , y el proveedor elegido de etiquetas es $ tagfull .

TAGFULID=${#@} TAGFUL=${!TAGFULID} ## Use xattr to read all existing tags: ATTRS=$(xattr "$TAGFUL") for f in "$@" ## For every selected file in Finder, do: do if("$TAGFUL"="$f") ## Is the supplier of tags is amongst the selected files? then break fi if [[ "$ATTRS" == *kMDItemUserTags* ]] ## Are there tags? then ## Load tags: TAGS=$(xattr -px com.apple.metadata:_kMDItemUserTags "$TAGFUL") ## Write tags: xattr -wx com.apple.metadata:_kMDItemUserTags "$TAGS" "$f" fi if [[ "$ATTRS" == *FinderInfo* ]] ## Are there colours? then ## Load colour: FINDERINFO=$(xattr -px com.apple.FinderInfo "$TAGFUL") ## Write colour: xattr -wx com.apple.FinderInfo "$FINDERINFO" "$f" fi done


El marco OpenMeta es un estándar de terceros para agregar metadatos a archivos OS X usando atributos extendidos. Es utilizado por una serie de aplicaciones de terceros.

O puede usar el comando XATTR para manipular los atributos extendidos a través de la línea de comandos.



Esto no cubre las etiquetas, pero para cambiar los colores de las etiquetas, una forma de hacerlo es a través de un comando como este:

xattr -wx com.apple.FinderInfo / 0000000000000000000400000000000000000000000000000000000000000000 myfile.txt

El 04 enterrado en el medio está configurando el color del archivo.

Aquí hay una secuencia de comandos de Python que envuelve ese comando que le permite establecer el color de la etiqueta en un archivo o serie de archivos:

import sys 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))

El uso es:

labelcolor.py [color] *.jpg

donde [color] es un nombre o abreviatura como se define a continuación:

clear (c), grAy (a), green (g), purple (p), blue (b), yellow (y), red (r), orange (o)


Lo siento por agregar otra respuesta, pero la relacionada con la configuración de los colores de la etiqueta ya era bastante larga. Aquí hay un extracto de un script de python que utilizo para establecer las etiquetas de usuario. Parece funcionar para hacer que las cosas se puedan buscar, pero no estoy seguro de si las etiquetas se mostrarán correctamente. El uso es básicamente:

tagfile.py "Tag Name" FileOrFolderName

Código abajo.

#! /usr/bin/env python # -*- coding: utf-8 -*- """ Write tags to file Usage: tagfile.py "TagName" FileName1 FileName2 You can use wildcards for the file name. Use quotes if spaces in tags. To check if it worked, use xattr -l FileName """ import sys import subprocess def writexattrs(F,TagList): """ writexattrs(F,TagList): writes the list of tags to three xattr fields on a file-by file basis: "kMDItemFinderComment","_kMDItemUserTags","kMDItemOMUserTags Uses subprocess instead of xattr module. Slower but no dependencies""" Result = "" plistFront = ''<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><array>'' plistEnd = ''</array></plist>'' plistTagString = '''' for Tag in TagList: plistTagString = plistTagString + ''<string>{}</string>''.format(Tag.replace("''","-")) TagText = plistFront + plistTagString + plistEnd OptionalTag = "com.apple.metadata:" XattrList = ["kMDItemFinderComment","_kMDItemUserTags","kMDItemOMUserTags"] for Field in XattrList: XattrCommand = ''xattr -w {0} /'{1}/' "{2}"''.format(OptionalTag + Field,TagText.encode("utf8"),F) if DEBUG: sys.stderr.write("XATTR: {}/n".format(XattrCommand)) ProcString = subprocess.check_output(XattrCommand, stderr=subprocess.STDOUT,shell=True) Result += ProcString return Result DEBUG = False if __name__ == "__main__": if len(sys.argv) < 3: print __doc__ else: TagList = [ sys.argv[1] ] # print TagList # Or you can hardwire your tags here # TagList = [''Orange'',''Green''] FileList = sys.argv[2:] for FileName in FileList: writexattrs(FileName, TagList)


Podrías darle una oportunidad a esto:

xattr -w com.apple.metadata:_kMDItemUserTags ''<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><array><string>Orange</string><string>Red</string></array></plist>'' $currentFile

Querrá reemplazar $ currentFile con el archivo al que desea agregar etiquetas y cambiar

<string>Orange</string><string>Red</string>

a una lista de las etiquetas que desee agregar.



A partir de Mavericks, es posible obtener y establecer etiquetas de color en Cocoa, utilizando NSURL .

NSURL tiene una gran cantidad de propiedades que se pueden establecer o leer, a través de los respectivos setResourceValue:forKey:error: y getResourceValue:forKey:error:

Usando la clave NSURLLabelNumberKey , puede establecer las etiquetas de color de la siguiente manera:

NSURL *fileURL = [NSURL fileURLWithPath:@"/Users/[username]/Documents/[some_file]"]; NSError *resourceError; if (![fileURL setResourceValue:@(2) forKey:NSURLLabelNumberKey error:&resourceError]) { NSLog(@"Error while setting file resource: %@", [resourceError localizedDescription]); }

Si esto se ejecuta en un archivo que solo tiene un color, borra el color actual y establece el color especificado. Sin embargo, si ya hay varios colores establecidos en el archivo, entonces no borra los colores existentes antes de configurar el color especificado.

Aquí está el mapeo valor-color (en El Capitán):

  • @ (0): Ninguno
  • @ (1): Gris
  • @ (2): Verde
  • @ (3): Púrpura
  • @ (4): Azul
  • @ (5): Amarillo
  • @ (6): Rojo
  • @ (7): Naranja

No he podido establecer una etiqueta utilizando NSURLLabelColorKey . Aquí está mi experiencia en El Capitán, con las claves relacionadas con ''etiquetas'' (Colores):

  • NSURLLabelNumberKey : se puede leer / configurar con éxito, con los números 0-7. Cualquier otro número devolverá un error. Si hay varias etiquetas establecidas, esto devolverá el índice del primer color establecido, ya que busca numéricamente a través de los índices 1 a 7. Aunque puede borrar un color en el Finder haciendo clic en el color, programando un color que ya está establecido no borra ese color.
  • NSURLLabelColorKey : devuelve nil, incluso cuando se establece una etiqueta de color para un archivo. Establecer un valor con esta tecla no tiene efecto.
  • NSURLTagNamesKey : devuelve una matriz de los nombres de color para las etiquetas que se establecen.

A partir de Mavericks, también es posible establecer etiquetas de colores en Cocoa, utilizando NSAppleScript .

NSURL *fileURL = [NSURL fileURLWithPath:@"/Users/sheaparis/Documents/filezilla_sites.xml"]; //Format the filepath for the AppleScript environment. // Without this, the file cannot be found. NSString *filepath = [fileURL path]; NSString *appleScriptFilePath = [filepath stringByReplacingOccurrencesOfString:@"/" withString:@":"]; if ([appleScriptFilePath hasPrefix:@":"]) { appleScriptFilePath = [appleScriptFilePath substringFromIndex:1]; } NSLog(@"appleScriptFilePath: %@", appleScriptFilePath); //Tells Finder to set the Red color tag for the specified file NSString *sourceString = [NSString stringWithFormat: @"set theFile to /"%@/" as alias/n" "tell application /"Finder/" to set label index of theFile to 2", appleScriptFilePath]; NSAppleScript *script = [[NSAppleScript alloc] initWithSource:sourceString]; NSDictionary *scriptErrorDict = nil; [script executeAndReturnError:&scriptErrorDict]; if (scriptErrorDict) { NSLog(@"errorDict: %@", scriptErrorDict); }

Si esto se ejecuta en un archivo que solo tiene un color, borra el color actual y establece el color especificado. Sin embargo, si ya hay varios colores establecidos en el archivo, entonces no borra los colores existentes antes de configurar el color especificado.

Usando el entorno AppleScript , la asignación de colores es la siguiente:

  • 0: ninguno
  • 1: naranja
  • 2: rojo
  • 3: amarillo
  • 4: azul
  • 5: púrpura
  • 6: verde
  • 7: gris