Cómo configurar los metadatos de "fecha agregada" en Mac OS X 10.7 Lion

El Finder en Mac OS X 10.7 Lion muestra una nueva pieza de metadatos de archivo, "Fecha de adición", que rastrea la fecha en que se agregó un elemento a una carpeta. Después de actualizar a 10.7, ninguno de los elementos de mi ~/Downloadscarpeta tiene valores de "Fecha de adición". Me gustaría establecer todos los valores vacíos de "Fecha de adición" para que coincidan con los valores de "Fecha de modificación", pero no sé cómo establecer el atributo "Fecha de adición" en un valor específico.

Mi primera conjetura fue esta:

xattr -w com.apple.metadata:kMDItemDateAdded "2012-02-19 16:34:47 +0000" myfile

Pero eso no parece funcionar (aunque tampoco informa de un error).

¿Al final encontraste una solución?
La respuesta aceptada funcionó cuando lo probé (por loco que sea).

Respuestas (5)

OK, nuevo enfoque aquí. Precaución: no tengo un sistema actualizado a Lion (mi computadora vino con Lion instalado), así que no puedo probar esto. Código no probado; copia de seguridad antes de probar este código!

Mi respuesta anterior se basó en el orden de clasificación utilizado por la pila de Descargas en el Dock. El campo Fecha de adición en el Finder parece estar basado en información de Spotlight, que es difícil de piratear. Tampoco es accesible a través de AppleScript. Pero, parece haber una solución.

  1. Cree un nuevo flujo de trabajo en Automator.

  2. Configure el flujo de trabajo para aceptar archivos o carpetas del Finder agregando la acción "Solicitar elementos del Finder".

  3. Haga que el flujo de trabajo ejecute un AppleScript agregando la acción "Ejecutar AppleScript".

Utilice este AppleScript:

on run {input, parameters}
    do shell script "sudo /usr/sbin/systemsetup -setusingnetworktime Off" with administrator privileges
    tell application "Finder"
        repeat with x in input
            set myfile to POSIX path of x
            set nm to name of x
            set d to modification date of x
            set yr to (character 3 of (year of d as string)) & (character 4 of (year of d as string))
            set mth to (month of d as number) as string
            if length of mth is 1 then set mth to "0" & mth
            set dy to day of d as string
            if length of dy is 1 then set dy to "0" & dy
            set h to hours of d as string
            if length of h is 1 then set h to "0" & h
            set m to minutes of d as string
            if length of m is 1 then set m to "0" & m
            set s to seconds of d as string
            if length of s is 1 then set s to "0" & s
            set dt to mth & ":" & dy & ":" & yr as string
            set tm to h & ":" & m & ":" & s as string
            do shell script "sudo /usr/sbin/systemsetup -setdate '" & dt & "'" with administrator privileges
            do shell script "sudo /usr/sbin/systemsetup -settime '" & tm & "'" with administrator privileges
            do shell script "mv \"" & myfile & "\" /var/tmp/clobber"
            do shell script "mv /var/tmp/clobber \"" & myfile & "\""
        end repeat
    end tell
    do shell script "sudo /usr/sbin/systemsetup -setusingnetworktime On" with administrator privileges
    return input
end run

Seleccione los archivos que aún no tienen una Fecha de adición (ordene por Fecha de adición en Finder, luego seleccione la parte de la lista sin Fecha de adición) y ejecute este servicio.

captura de pantalla del flujo de trabajo en Automator

Eso es horrible... en el buen sentido, ¿quizás?
Bueno, definitivamente es un truco. Pero parece que esa parte particular de los metadatos se calcula a partir de Spotlight, y sin piratear el oscuro misterio conocido como /.Spotlight-V100, esto podría ser lo mejor posible. Pero me encantaría ver una respuesta limpia.
¿Estoy recibiendo un error extraño de este script? sh: -c línea 0: EOF inesperado mientras busca coincidencias `"
@erotsppa debería corregirse y actualizarse ahora.
El AppleScript se detuvo con un error al procesar un archivo que tenía $en su nombre, pero lo solucioné cambiando temporalmente el nombre de ese archivo. Para hacer que AppleScript maneje dichos archivos, mis búsquedas indican que podría reemplazarlos myfilecon quoted form of myfile, pero no lo he probado. Si uno intentara eso, podría ser más claro citar al configurar myfiley cambiar el nombre de la variable a quotedFilePath.
A partir de mayo de 2019, este truco aún parece ser la única forma de hacerlo y no parece que vaya a cambiar. Ninguna herramienta de secuencias de comandos o CLI puede ayudar más porque las API más profundas para acceder a los atributos del sistema de archivos solo mencionan "fechas de creación" y "modificación" (el utime de nivel BSD() y el FileManager/FileAttributeKey de nivel Foundation) o mencionan la "fecha agregada" como valor de solo lectura (Foundation/URL/URLResourceKey).

Cuando ejecuto xattr -lelementos en mi carpeta Descargas, obtengo un campo que se parece a esto:

com.apple.metadata:kMDItemDownloadedDate:
00000000  62 70 6C 69 73 74 30 30 A1 01 33 41 B4 83 4D BF  |bplist00..3A..M.|
00000010  4C 4F E3 08 0A 00 00 00 00 00 00 01 01 00 00 00  |LO..............|
00000020  00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 13                                   |.....|
00000035

Esta es una plist binaria. Cuando uso HexFiend para crear un archivo con esos bytes (sí, los ingresé manualmente; volví del pasado como ingresar el código ensamblador de una revista en mi Apple ][GS), luego lo guardé como un archivo .plist, abrí el archivo en TextWrangler y obtuve el siguiente xml sin compilar:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <date>2011-11-28T05:03:59Z</date>
</array>
</plist>

Dicho esto, aunque Apple parece almacenar las fechas en XML compilado, el texto sin formato parece funcionar.

En otras palabras, si puede obtener la fecha de modificación del archivo en forma de cadena, puede ejecutar el comando xattr -w com.apple.metadata:kMDItemDownloadedDate "2012-02-19 16:34:47 +0000" filepara cambiar la "fecha de descarga", que parece ser el campo realmente ordenado, no la fecha real agregada.

Finalmente, no recibió ningún error al agregar el kMDItemDateAddedcampo (no utilizado) porque, como aprendí en este artículo , xattrconfigurará felizmente cualquier campo de metadatos que desee, usado o no usado.

Ese es el núcleo de la respuesta. Trabajaré en escribir un AppleScript para obtener la fecha de modificación de cada archivo, verificaré si kMDItemDownloadedDateestá configurado y, si no lo está, configure kMDItemDownloadedDate en la fecha de modificación, pero quería publicar el núcleo de la respuesta.

Ejecute mdls en los archivos de su carpeta Descargas y verá los valores de kMDItemDateAdded. Eso es lo que muestra la columna "Fecha de adición" en la vista de lista del buscador.
Por cierto, si desea mostrar kMDItemDownloadedDate como información de plist sin pasar por HexFiend y TextWrangler, intente xattr -p com.apple.metadata:kMDItemDownloadedDate FILENAME_HERE | xxd -r -p | plutil -convert xml1 - -o -. El xxd convierte a datos plist binarios, luego los plutilconvierte a plist XML y los imprime.
OK, estoy sobre mi cabeza, tengo miedo de decir. kMDItemDateAdded no aparece en xattr -l, y kMDItemDownloadedDate no aparece en mdls. Más y más curioso. Tampoco se almacena el campo Fecha de adición en un xattr para el directorio . ¿Dónde viven estos metadatos?
Dado que xattres una secuencia de comandos de Python, supongo que debería ser posible hurgar en esta secuencia de comandos y descubrir cómo obtener los datos binarios del atributo en binario, en lugar de hexadecimal, para que pueda enviarlo directamente a plutil.

No puedo encontrar una manera de configurar la "Fecha de agregado" que se muestra en el Finder.

Creo que tiene razón en que se recupera del kMDItemDateAddedatributo de metadatos del índice de Spotlight. Sin embargo, Spotlight parece derivar esto de alguna manera.

Intenté configurar un atributo de archivo extendido llamado com.apple.metadata:kMDItemDateAddeda un valor de fecha en uno de varios formatos diferentes, incluido el formato utilizado por kMDItemDateAddedy ninguno de ellos fue recogido por el índice de Spotlight, es decir, sin importar el valor mostrado por xattr, el valor mostrado por mdlsno se modificó.

Supongo , aunque no estoy seguro, que Spotlight simplemente establece esta fecha en función de la primera vez que indexa un archivo en una ubicación particular y no verifica ningún otro metadato para generarlo. Si mvun archivo sale de Descargas y vuelve a entrar, la Fecha de agregado se actualiza cuando se volvió a mover, pero ninguno de los metadatos del archivo parece afectado, solo los metadatos de Spotlight.

Entonces, en resumen, creo que la fecha agregada solo se almacena en algún lugar en las entrañas bastante crípticas de /.Spotlight-V100, y a menos que alguien pueda encontrar una forma de decirle a Spotlight que actualice una entrada de metadatos a un valor arbitrario, puedo ' No veo una manera de hacer esto.

¡Destacar! Bien hecho.

¡Gracias a Daniel Lawson por la solución! Todavía funciona bien, incluso dos años después.

Tengo dos adiciones:

1) Tenga en cuenta que hay un pequeño error en el código de la respuesta aceptada.

Esta línea:

do shell script "/usr/sbin/systemsetup -settime ''" & tm & "'"

... tiene un apóstrofo adicional, lo que desencadena un error "EOF inesperado". Debería leer:

do shell script "/usr/sbin/systemsetup -settime '" & tm & "'"

2) Más importante aún, a partir de Mavericks 10.9.2, la configuración del sistema requiere derechos de administrador. Entonces, cada llamada al script de shell debe seguir esta fórmula:

do shell script "sudo /usr/sbin/systemsetup -setusingnetworktime Off" with administrator privileges

Aquí está la versión modificada completa de AppleScript, que se confirmó que funciona en 10.9.3:

on run {input, parameters}
    do shell script "sudo /usr/sbin/systemsetup -setusingnetworktime Off" with administrator privileges

    tell application "Finder"
        repeat with x in input
            set myfile to POSIX path of x
            set nm to name of x

            set d to modification date of x
            set yr to (character 3 of (year of d as string)) & (character 4 of (year of d as string))
            set mth to (month of d as number) as string
            if length of mth is 1 then set mth to "0" & mth
            set dy to day of d as string
            if length of dy is 1 then set dy to "0" & dy
            set h to hours of d as string
            if length of h is 1 then set h to "0" & h
            set m to minutes of d as string
            if length of m is 1 then set m to "0" & m
            set s to seconds of d as string
            if length of s is 1 then set s to "0" & s

            set dt to mth & ":" & dy & ":" & yr as string
            set tm to h & ":" & m & ":" & s as string
            do shell script "sudo /usr/sbin/systemsetup -setdate '" & dt & "'" with administrator privileges
            do shell script "sudo /usr/sbin/systemsetup -settime '" & tm & "'" with administrator privileges

            do shell script "mv \"" & myfile & "\" /var/tmp/clobber"
            do shell script "mv /var/tmp/clobber \"" & myfile & "\""
        end repeat
    end tell

    do shell script "sudo /usr/sbin/systemsetup -setusingnetworktime On" with administrator privileges

    return input
end run
¡Bienvenido a Ask Different! En lugar de escribir una respuesta para editar la respuesta de otra persona, simplemente haga clic en el botón editar o mejorar esta respuesta debajo de la publicación que desea mejorar .
La respuesta de Daniel ha sido editada para incluir estos cambios.

Si se siente cómodo compilando algún código C, entonces, como señaló Ken Thomases , estos datos se pueden recuperar de getattrlist(2). Y aunque parece que el correspondiente settralist(2)no funcionó para la fecha agregada en versiones anteriores de macOS, el siguiente código me funciona en macOS Monterey 12.5.1, ajustando la fecha que se muestra en Finder.

Es solo obtener y configurar el ATTR_CMN_ADDEDTIMEatributo, que el manual describe como

la hora en que el objeto del sistema de archivos se creó o cambió de nombre en su directorio contenedor. Tenga en cuenta que se puede observar un comportamiento incoherente cuando se solicita este atributo en elementos con enlaces fijos.

#include <stdlib.h>
#include <string.h>
#include <sys/attr.h>
#include <unistd.h>

/*
 * Get kMDItemDateAdded of path.
 *
 * Returns:
 *   • 0 on success
 *   • 1 if a system call failed: check errno
 *   • 2 if something else went wrong
 */
int get_date_added(const char* path, struct timespec * out) {
    attrgroup_t request_attrs = ATTR_CMN_RETURNED_ATTRS | ATTR_CMN_ADDEDTIME;

    struct attrlist request;
    memset(&request, 0, sizeof(request));
    request.bitmapcount = ATTR_BIT_MAP_COUNT;
    request.commonattr = request_attrs;

    typedef struct {
        u_int32_t length;
        attribute_set_t returned;
        struct timespec added;
    } __attribute__((aligned(4), packed)) response_buf_t;

    response_buf_t response;

    int err = getattrlist(path, &request, &response, sizeof(response), 0);
    if (err != 0) {
        return 1;
    }
    if (response.length != sizeof(response)) {
        // Need a different-sized buffer; but provided one of exactly required
        // size?!
        return 2;
    }
    if (response.returned.commonattr != request_attrs) {
        // Didn’t get back all requested common attributes
        return 2;
    }

    out->tv_sec = response.added.tv_sec;
    out->tv_nsec = response.added.tv_nsec;

    return 0;
}

/*
 * Set kMDItemDateAdded of path.
 *
 * Returns:
 *   • 0 on success
 *   • 1 if a system call failed: check errno
 */
int set_date_added(const char* path, struct timespec in) {
    attrgroup_t request_attrs = ATTR_CMN_ADDEDTIME;

    struct attrlist request;
    memset(&request, 0, sizeof(request));
    request.bitmapcount = ATTR_BIT_MAP_COUNT;
    request.commonattr = request_attrs;

    typedef struct {
        struct timespec added;
    } __attribute__((aligned(4), packed)) request_buf_t;

    request_buf_t request_buf;
    request_buf.added.tv_sec = in.tv_sec;
    request_buf.added.tv_nsec = in.tv_nsec;

    int err = setattrlist(path, &request, &request_buf, sizeof(request_buf), 0);
    if (err != 0) {
        return 1;
    }

    return 0;
}
hola me podrias explicar como se usa por favor 1. cómo hacer que este código se ejecute realmente y 2. ¿cómo llamarlo?