如何在Linux中获取文件创建日期?

12

我正在处理一批文件,这些文件包含同一个对象在其生命周期的不同时间的信息,而唯一的排序方式是按创建日期排序。 我曾经使用过这个:

//char* buffer has the name of file
struct stat buf;
FILE *tf;
tf = fopen(buffer,"r");
//check handle
fstat(tf, &buf);
fclose(tf);
pMyObj->lastchanged=buf.st_mtime;

但是它似乎不起作用。我做错了什么?在Linux下获取文件创建日期还有其他更可靠/简单的方法吗?


3
fstat不能获取“文件创建”时间戳值,因为许多文件系统不跟踪该数据。你正在使用哪个文件系统? - nobody
我想应该是最新的Ubuntu桌面标准吧 - 我正在虚拟机上运行我的代码(确切地说是vmware player),并将文件系统等所有细节留给了Ubuntu安装程序。 - Srv19
尝试使用stat(buffer, &buf)代替无用的fopen - mpez0
1
如果代码编译没有警告,那么你的编译器存在重大问题。如果代码编译时出现警告,请注意有关不正确参数类型(或指针到整数的转换)的警告并修复代码,使其无警告编译通过。 - Jonathan Leffler
5个回答

16
最接近“创建日期”的近似值是struct stat 中的st_ctime 成员,但实际上记录的是 i-node 更改的最后时间。如果您创建文件并从未修改它的大小或权限,则它可以用作创建时间。否则,在标准 Unix 系统中没有记录文件创建时间。
为达到您的目的,请按 st_mtime 进行排序…或获取文件名中带有时间戳的文件。
请注意,如果您在 Darwin(Mac OS X)上,可以获得创建时间。来自stat(2)手册页面:

然而,当宏定义_DARWIN_FEATURE_64_BIT_INODE存在时,stat结构现在将被定义为:

 struct stat { /* when _DARWIN_FEATURE_64_BIT_INODE is defined */
     dev_t           st_dev;           /* ID of device containing file */
     mode_t          st_mode;          /* Mode of file (see below) */
     nlink_t         st_nlink;         /* Number of hard links */
     ino_t           st_ino;           /* File serial number */
     uid_t           st_uid;           /* User ID of the file */
     gid_t           st_gid;           /* Group ID of the file */
     dev_t           st_rdev;          /* Device ID */
     struct timespec st_atimespec;     /* time of last access */
     struct timespec st_mtimespec;     /* time of last data modification */
     struct timespec st_ctimespec;     /* time of last status change */
     struct timespec st_birthtimespec; /* time of file creation(birth) */
     off_t           st_size;          /* file size, in bytes */
     blkcnt_t        st_blocks;        /* blocks allocated for file */
     blksize_t       st_blksize;       /* optimal blocksize for I/O */
     uint32_t        st_flags;         /* user defined flags for file */
     uint32_t        st_gen;           /* file generation number */
     int32_t         st_lspare;        /* RESERVED: DO NOT USE! */
     int64_t         st_qspare[2];     /* RESERVED: DO NOT USE! */
 };

注意 st_birthtimespec 字段。同时请注意,所有时间均以 struct timespec 值表示,因此具有亚秒定时(tv_nsec 为纳秒分辨率)。 POSIX 2008 <sys/stat.h> 要求在标准时间上使用 struct timespec 计时,而 Darwin 遵循了这一点。


遗憾的是,这些文件是由另一个应用程序创建的。遗憾的是,我没有权限对其进行任何更改。 - Srv19

9

fstat在文件描述符上工作,而不是FILE结构。最简单的版本:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>

#ifdef HAVE_ST_BIRTHTIME
#define birthtime(x) x.st_birthtime
#else
#define birthtime(x) x.st_ctime
#endif

int main(int argc, char *argv[])
{
        struct stat st;
        size_t i;

        for( i=1; i<argc; i++ )
        {
                if( stat(argv[i], &st) != 0 )
                        perror(argv[i]);
                printf("%i\n", birthtime(st));
        }

        return 0;
}

您需要通过检查sys / stat.h或使用某种autoconf结构来确定您的系统是否具有stat结构中的st_birthtime。

那么,我该如何获取文件描述符呢? - Srv19
1
@srv19 你可以使用open(2)或者使用fileno(tf)来获取文件描述符。然而,我提供给你的是一种在不打开文件的情况下检查它属性的方法。如果你需要打开文件并且想要使用stdio函数,那么fileno是你的好朋友。 - Mel
你的解决方案解决了我的问题。非常感谢。我怀疑在使用fstat时漏掉了什么。 - Srv19

6

文件创建时间没有被存储在任何地方,你只能获取以下其中之一:

time_t    st_atime;   /* time of last access */
time_t    st_mtime;   /* time of last modification */
time_t    st_ctime;   /* time of last status change */

你的代码应该给你最后修改时间。注意:你可以使用stat()而不是fstat()来获取文件信息(stat()需要文件名作为参数,而不需要打开文件)。

啊,我疏忽了,你传递给fstat的是FILE指针,而不是描述符 :) - Code Painters

6
要在Linux中获取文件的创建日期,我使用以下方法:
root@sathishkumar# cat << _eof > test.txt 
> Hello
> This is my test file
> _eof
root@sathishkumar# cat test.txt 
Hello
This is my test file
root@sathishkumar# ls -i test.txt 
2097517 test.txt
root@sathishkumar# debugfs -R 'stat <2097517>' /dev/sda5

Inode: 2097517   Type: regular    Mode:  0664   Flags: 0x80000
Generation: 4245143992    Version: 0x00000000:00000001
User:  1000   Group:  1000   Size: 27
File ACL: 0    Directory ACL: 0
Links: 1   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x50ea6d84:4826cc94 -- Mon Jan  7 12:09:00 2013
 atime: 0x50ea6d8e:75ed8a04 -- Mon Jan  7 12:09:10 2013
 mtime: 0x50ea6d84:4826cc94 -- Mon Jan  7 12:09:00 2013
 crtime: 0x5056d493:bbabf49c -- Mon Sep 17 13:13:15 2012
Size of extra inode fields: 28
EXTENTS:
(0):8421789

atime: 上次打开或执行文件的时间

ctime: inode 信息更新的时间。当文件被修改时,ctime 也会更新。

mtime: 最后修改时间

crtime: 文件创建时间


3
谢谢您的回答,但我必须指出我的问题是关于Linux核心C函数的使用,而不是如何在shell中获取创建时间。 - Srv19

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接