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 ~/Downloads
carpeta 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).
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.
Cree un nuevo flujo de trabajo en Automator.
Configure el flujo de trabajo para aceptar archivos o carpetas del Finder agregando la acción "Solicitar elementos del Finder".
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.
/.Spotlight-V100
, esto podría ser lo mejor posible. Pero me encantaría ver una respuesta limpia.$
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 myfile
con quoted form of myfile
, pero no lo he probado. Si uno intentara eso, podría ser más claro citar al configurar myfile
y cambiar el nombre de la variable a quotedFilePath
.Cuando ejecuto xattr -l
elementos 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" file
para 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 kMDItemDateAdded
campo (no utilizado) porque, como aprendí en este artículo , xattr
configurará 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 kMDItemDownloadedDate
está configurado y, si no lo está, configure kMDItemDownloadedDate en la fecha de modificación, pero quería publicar el núcleo de la respuesta.
xattr -p com.apple.metadata:kMDItemDownloadedDate FILENAME_HERE | xxd -r -p | plutil -convert xml1 - -o -
. El xxd convierte a datos plist binarios, luego los plutil
convierte a plist XML y los imprime.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?xattr
es 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 kMDItemDateAdded
atributo 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:kMDItemDateAdded
a un valor de fecha en uno de varios formatos diferentes, incluido el formato utilizado por kMDItemDateAdded
y ninguno de ellos fue recogido por el índice de Spotlight, es decir, sin importar el valor mostrado por xattr
, el valor mostrado por mdls
no 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 mv
un 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.
¡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
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_ADDEDTIME
atributo, 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;
}
erotsppa
Juan Siracusa