So, I've further messed with the code kindly offered by andrew and Stefan Schmidt, and here's a bit of C code that you can run after you copy your folders.
(To be clear for the unfamiliar - this is code you will need to paste into an editor, compile and run; if you are unfamiliar with that look into running C code on a Mac.)
You'll need to assert admin privileges, run it as root, and sudo that sucker, lest it fail editing a bunch of files for no clear reason. Once the code is running, you just write the path to the folder where the Date Added info is the way God intended (or just drag the folder itself into the Terminal window), press Enter, and then write the path to the folder copy (or again just drag it in), and that folder copy will receive the dates of the original!
(I must stress, the folder with the right dates goes FIRST! If you mix them up and run the code the wrong dates will irreversibly overwrite the right ones!)
For your sake, I suggest making sure to only point it to folders whose dates you actually care about, lest it run for half an hour filling your logs with Application Support garbage that has never been relevant to anyone in human history.
Code works in my test, but hey, if there's issues with it, don't be surprised, all I knew about C two days before posting this was it existed.
EDIT: updated the code to make it more user-friendly and give more informational warnings, and the answer for similar reasons.
#include <stdlib.h>
#include <string.h>
#include <sys/attr.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/errno.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?
*/
int ok=0;
int nok=0;
int logs=1;
void list(char *basePathSource, char *basePathDest){
char path[9000];
char pathd[9000];
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=basePath+'/'+dp->d_name
int terr = date_added_transfer(path, pathd);
if(terr==0){
ok++;
if(logs>=2)printf("Successfully transferred Date Added to %s! :D\n", pathd);
}else nok++;
if (terr==2) if(logs<=2)printf("Failed to get 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) {
if(logs<=2)printf("Failed to get Date Added from %s: '%s' :c \n", path,strerror(errno));
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) {
if(logs<=2)printf("Failed to set Date Added to %s: '%s' :c \n", path,strerror(errno));
return 1;
}
return 0;
}
int date_added_transfer(char* paths, char* pathd) {
int err;
if(access(paths, F_OK) != 0) {
if(logs<=2)printf("Can't reach source path %s :c\n", paths);
return 1;
}
if(access(pathd, F_OK) != 0) {
if(logs<=2)printf("Can't reach destination path %s - it's probably not there\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 3;
}
return 0;
}
int main(){
char srcpath[100];
char dstpath[100];
int logset;
int loopn=1;
// Input paths from user
while(loopn==1){
ok=0;
nok=0;
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);
printf("You'll be told how many successful and failed transfers occurred, In addition, type the number of the option you prefer:\n");
printf("1. Failure messages only, 2. Failure and success messages, or 3. Success messages only\n");
scanf("%d", &logset);
logs=logset;
printf("Righty then, let's go!\n");
list(srcpath, dstpath);
printf("%d transfers successful, %d transfers failed\n",ok,nok);
printf("Wanna go again? 1. Yep! 2. Nah that's it!\n");
scanf("%d", &loopn);
}
return 0;
}