【问题标题】:How do I change the creation time of a file to a newer date in Mac OS X?如何在 Mac OS X 中将文件的创建时间更改为较新的日期?
【发布时间】:2016-08-10 09:26:43
【问题描述】:

在 Mac OS X 上,使用 C 和/或 C++,我想将文件的创建时间更改为任意日期/时间。我找到了许多解决方案,特别是 this StackOverflow answer,允许将创建时间设置为 older 日期,但这对我来说还不够 - 我还希望能够设置 较新日期。因此,使用 utimes() 函数不是我正在寻找的解决方案。

我知道必须以某种方式设置更新的创建时间,因为来自 Apple 开发人员命令行工具的 SetFile 实用程序可以做到这一点,但到目前为止,我的 search-fu 未能发现任何让我更接近的提示一个解决方案。

有谁知道我如何实现目标?

为什么我要自己做,为什么不能用SetFile?

  • SetFile 命令行实用程序已被弃用(请参阅 man SetFile),因此它肯定会在未来一段时间内消失
  • 我想创建一个实用程序,允许我指定时间增量以添加到当前创建时间/从当前创建时间减去。 SetFile 实用程序没有任何方便的命令行参数来执行此操作。
  • 最后但同样重要的是:好奇心!

【问题讨论】:

  • 使用utime 无论如何都不起作用,因为您只能使用它设置访问和修改时间,而不是创建时间。要更改创建时间,唯一的方法是创建一个新文件,复制内容并将其重命名为新文件。那么创建时间将是“现在”。在用户空间中,一旦设置创建时间,您就无法更改它。
  • @JoachimPileborg 如果您阅读我引用的答案,您会看到utimes() 在某些情况下会调整创建时间。 Here's a direct link 到指定行为的 utimes() 的 BSD 手册页。我承认我自己没有测试过这种行为,但是如果你在命令行上运行touch -t 并设置一个比文件当前创建时间更早的修改时间,它的操作就很明显了。
  • 大多数 Unix 文件系统甚至不存储创建时间。

标签: c++ c macos


【解决方案1】:

没试过,但根据文档,NSURLCreationDateKey 键下的NSURL 资源值是可读写的。由于您指定了 C 或 C++,因此您将使用相应的 CFURL API。所以,你会打电话:

CFURLRef url = /* ... */
CFDateRef date = /* ... */
CFErrorRef error;
if (!CFURLSetResourcePropertyForKey(url, kCFURLCreationDateKey, date, &error))
    /* handle error */;

编辑:一个最小的例子

const char* fileName = "/path/to/file";
size_t fileNameStringLength = strlen(fileName);
Boolean isDirectory = false;
CFURLRef url = CFURLCreateFromFileSystemRepresentation(
   kCFAllocatorDefault,
   (const UInt8*)fileName,
   fileNameStringLength,
   isDirectory);

// Seconds since 1 January, 2001 00:00:00 GMT
CFAbsoluteTime absTime = CFAbsoluteTimeGetCurrent();
CFAbsoluteTime adjustedCreationTime = absTime - 3600;
CFDateRef date = CFDateCreate(
    kCFAllocatorDefault,
    adjustedCreationTime);

CFErrorRef error;
if (!CFURLSetResourcePropertyForKey(url, kCFURLCreationDateKey, date, &error))
{
  fprintf(stderr, "an error occurred\n");
  exit(1);
}

CFRelease(url);
CFRelease(date);

【讨论】:

  • 我用一个最小的例子对此进行了测试,它确实有效!然而,仅仅把这个例子放在一起就很麻烦,因为我不熟悉 Core Foundation。与此同时,我找到了一个同样有效的替代方法,它使用了 Objective-C / Cocoa (link to the SO answer)。我会选择那个解决方案,因为 C/C++ 可以很容易地与 Objective-C 混合使用,而且使用 Cocoa 的更高级别的 API 可以轻松得多。
【解决方案2】:

顺便说一句,我不知道这是否安全,可靠,无论如何。所以,这样做需要您自担风险。

在 OS X 上,您可以通过将一天中的时间设置为未来然后复制文件(并将其重命名)来执行此操作。它不是同一个文件,其创建时间已修改;它是您设置的创建时间的副本。

一些代码(我从here得到了设置时间的代码):

#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <copyfile.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  struct timeval tv_now, tv_set;
  copyfile_state_t s;
  struct stat st;
  // retrieve original stat
  if (stat(argv[2], &st) < 0)
    perror("stat");
  // get current time of day
  if (gettimeofday(&tv_now, 0) == -1)
    perror("gettimeofday");
  // set time of day to +argv[1] days
  tv_set = tv_now;
  tv_set.tv_sec += 86400 * atoi(argv[1]);
  if (settimeofday(&tv_set, 0) == -1)
    perror("settimeofday to future");
  // copy the file to a temporary, copy everythig except stat
  s = copyfile_state_alloc();
  if (copyfile(argv[2], ".eighty_eight_miles_per_hour", s, COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_DATA) < 0)
    perror("copy file");
  copyfile_state_free(s);
  // rename it back to original name
  if (rename(".eighty_eight_miles_per_hour", argv[2]) < 0)
    perror("rename file");
  // restore file owner, group, and mode
  if (chown(argv[2], st.st_uid, st.st_gid) < 0)
    perror("chown");
  if (chmod(argv[2], st.st_mode) < 0)
    perror("chmod");
  // reset current time of day
  if (settimeofday(&tv_now, 0) == -1)
    perror("settimeofday back to now");

  return 0;
}

我将此程序称为flux_capacitor。第一个命令行参数是设置文件创建日期的天数,第二个参数是文件名。您必须以root 身份运行此程序才能设置时间。

请注意,我将delorean 及时发送了 2 天。

[ronin:~/Documents/CPP] aichao% touch delorean
[ronin:~/Documents/CPP] aichao% ls -l delorean
-rw-r--r--  1 aichao  staff  0 Aug 10 11:43 delorean
[ronin:~/Documents/CPP] aichao% su
Password:
sh-3.2# ./flux_capacitor 2 delorean
sh-3.2# exit
exit
[ronin:~/Documents/CPP] aichao% ls -l delorean
-rw-r--r--  1 aichao  staff  0 Aug 12  2016 delorean
[ronin:~/Documents/CPP] aichao% date
Wed Aug 10 11:43:47 EDT 2016

在 Finder 中:

请注意,我仅从文件的stat 恢复原始所有者、组和模式。我不认为你可以或想做更多的事情,但我不知道。显然,文件的链接将被破坏。

【讨论】:

  • 感谢您花时间整理这些内容。非常感谢幽默 :-) 但正如您自己指出的那样,这种解决方案并不理想。
  • 感谢您提出问题。这是我在 SO 的 40 天里最开心的一次 :-)
  • 让我想起了高中写的一个程序,将所有系统字体缩小为 1,几乎不可能用鼠标控制任何东西(gag 应用程序)。经常改变系统时间......这可能会更糟。 -- 日历、日志文件、电子邮件、到期日期、续订提示,天哪!
猜你喜欢
  • 2021-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-24
  • 2014-12-04
  • 1970-01-01
  • 2012-07-05
  • 1970-01-01
相关资源
最近更新 更多