31 votos

¿Cómo se establecen los metadatos de "fecha añadida" en Mac OS X 10.7 Lion?

El Finder de Mac OS X 10.7 Lion muestra una nueva pieza de metadatos de archivo, "Fecha de adición", que rastrea la fecha en que un elemento se añadió a una carpeta. Después de actualizar a 10.7, ninguno de los elementos de mi ~/Downloads tienen 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 puedo averiguar cómo establecer el atributo "Fecha de adición" a un valor específico.

Mi primera suposición 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).

0 votos

¿Ha acabado encontrando una solución?

1 votos

La respuesta aceptada funcionó cuando la probé (por disparatada que sea).

2voto

Mars Puntos 1

Así pues, he seguido trasteando con el código amablemente ofrecido por andrew y Stefan Schmidt y aquí tienes un poco de código C que puedes ejecutar después de copiar tus carpetas. Simplemente escriba la ruta a la carpeta donde el orden de Fecha Añadida es como Dios manda (o simplemente arrastre la propia carpeta a la ventana de Terminal), pulse Intro, y luego escriba la ruta a la copia de la carpeta, ¡y esa copia de la carpeta recibirá las fechas de la original! (Una vez más, ¡primero la carpeta con las fechas correctas! O las fechas erróneas sobrescribirán las correctas).

El código funciona en mi prueba, pero bueno, si hay problemas con él, no se sorprenda, todo lo que sabía acerca de C hace dos días era que existía

#include <stdlib.h>
#include <string.h>
#include <sys/attr.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
/* Code goes through all the files in the source folder and its subfolders
 * gets their Date Added
 * and sets it to the corresponding files in the destination folder
 * Neat, eh?
 */
/* List, finds all files and sub-directories of a given
 * directory in tree structure.
 * @param basePath Base path to traverse directory
 */
void list(char *basePathSource, char *basePathDest){
  char path[1000];
  char pathd[1000];
  struct dirent *dp;
  DIR *dir = opendir(basePathSource);
  if (!dir) return;

  while ((dp = readdir(dir)) != NULL){
    if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0){
        strcpy(path, basePathSource);   //these three lines are
        strcat(path, "/");              //equivalent to the Processing line
        strcat(path, dp->d_name);       //path=basePathSource+'/'+dp->d_name
        strcpy(pathd, basePathDest);   //these three lines are
        strcat(pathd, "/");              //equivalent to the Processing line
        strcat(pathd, dp->d_name);       //path=basePathSource+'/'+dp->d_name
        int terr = date_added_transfer(path, pathd);
        if (terr==1) printf("Can't reach path %s or %s :c\n", path, pathd);
        if (terr==2) printf("Failed to transfer Date Added from %s :c\n", path);
        list(path, pathd);
    }
  }
  closedir(dir);
}
/* 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;
}
/* Set kMDItemDateAdded of path to kMDItemFSContentChangeDate
 * Returns:
 *   • 0 on success
 *   • 1 if a path doesn't exist
 *   • 2 if a function call failed
 */
int date_added_transfer(char* paths, char* pathd) {
  int err;
  if(access(paths, F_OK) != 0) {
    printf("error: %s doesn't exist\n", paths);
    return 1;
  }
  if(access(pathd, F_OK) != 0) {
    printf("error: %s doesn't exist\n", pathd);
    return 1;
  }
  struct timespec out;
  err = get_date_added(paths, &out);
  if (err != 0) {
    return 2;
  }
  struct timespec in;
  in.tv_sec = out.tv_sec;
  in.tv_nsec = out.tv_nsec;
  err = set_date_added(pathd, in);
  if (err != 0) {
    return 2;
  }
  return 0;
}
/* Modify paths given as command line arguments
 * Returns:
 *   • 0 on success
 *   • 1 if a path doesn't exist
 *   • 2 if something else went wrong
 */
int main(){
  char srcpath[100];
  char dstpath[100];
  // Input paths from user
  printf("Enter folder you wish to copy Date Added info from: ");
  scanf("%s", srcpath);
  printf("Enter the corresponding folder in the destination to copy the info to: ");
  scanf("%s", dstpath);
  list(srcpath, dstpath);
  return 0;
}

0voto

miki Puntos 36

Basándose en el código de andrew aquí un programa que lee el valor "Fecha Modificada" de un fichero y escribe el valor en "Fecha Añadida".

Copie el código siguiente en un archivo llamado date_add_to_mod.c y compilarlo.

gcc -o date_add_to_mod date_add_to_mod.c

Llama al programa desde el directorio actual con una lista de archivos.

./date_add_to_mod file1 file2 file3

El código fuente de date_add_to_mod.c .

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

/*
 * For a list of files set "Date Added" in
 * macOS Finder to match "Date Modified"
 */

/*
 * 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_modified(const char* path, struct timespec * out) {

    attrgroup_t request_attrs = ATTR_CMN_RETURNED_ATTRS | ATTR_CMN_MODTIME;

    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 modified;
    } __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.modified.tv_sec;
    out->tv_nsec = response.modified.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;
}

/*
 * Set kMDItemDateAdded of path to kMDItemFSContentChangeDate
 *
 * Returns:
 *   • 0 on success
 *   • 1 if a path doesn't exist
 *   • 2 if a function call failed
 */
int date_added_to_modifed(char* path) {

    int err;

    if(access(path, F_OK) != 0) {
        printf("error: %s doesn't exist\n", path);
        return 1;
    } 

    struct timespec out;
    err = get_date_modified(path, &out);
    if (err != 0) {
        return 2;
    }

    struct timespec in;
    in.tv_sec = out.tv_sec;
    in.tv_nsec = out.tv_nsec;
    err = set_date_added(path, in);
    if (err != 0) {
        return 2;
    }

    return 0;
}

/*
 * Modify paths given as command line arguments
 *
 * Returns:
 *   • 0 on success
 *   • 1 if a path doesn't exist
 *   • 2 if something else went wrong
 */
int main(int argc, char **argv) {

    if (argc >= 2) {
        for (int i = 1; i < argc; ++i) {
            char *path = argv[i];
            int err = date_added_to_modifed(path);
            if (err == 0) {
                printf("%s\n", path);
            }
            else if (err == 2) {
                printf("an unknown error occured\n");
                return 2;
            }
        }
    }
    else {
        printf("usage: date_add_to_mod file1 file2 ...\n");
    }

    return EXIT_SUCCESS;
}

El programa funciona en MacOS Catalina, así que probablemente también en MacOS Big Sur (y MacOS Monterey, como se ha indicado anteriormente).

Más información getattrlist y setattrlist está disponible en las páginas de manual correspondientes.


No tengo ni experiencia seria ni conocimientos de programación en C pero la solución me funciona™.

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X