如何执行 ls 然后按创建日期对结果进行排序?

如何执行 ls 然后按创建日期对结果进行排序?

日期按什么顺序排列?当然不是字母数字顺序。

ls -lt按修改时间排序。但我需要创作时间。

答案1

大多数unices没有文件创建时间的概念。ls由于未记录信息,因此无法打印。如果您需要创建时间,请使用版本控制系统:定义创建时间为签到时间。

如果您的 UNIX 变体有创建时间,请查看其文档。例如,关于Mac OS X(我知道的唯一例子),使用ls -tU. Windows 还存储创建时间,但它并不总是暴露给 unix 实用程序的端口,例如 Cygwinls没有显示它的选项。该stat实用程序可以显示创建时间,在 GNU 实用程序中称为“出生时间”,因此在 Cygwin 下,您可以使用stat -c '%W %n' * | sort -k1n.

注意时间( ls -lc)不是文件创建时间,这是索引节点改变时间。每当文件发生任何更改(内容或元数据)时,inode 更改时间都会更新,但仅读取文件时 ctime 不会更新(即使 atime 已更新)。特别是,ctime 始终比 mtime(文件内容修改时间)更新,除非 mtime 已明确设置为将来的日期。

答案2

不幸的是,stat(2)API 没有提供获取文件创建时间的方法,因为它是不需要按照 Unix 标准。

但是,某些文件系统(如ext4XFS)确实将此信息保存在文件元数据中。只是没有标准的方法来获得它,但有一种方法:

注:本回答主要涉及Linux系统。

2021 年更新:新的ls命令选项

根据斯蒂芬·查泽拉斯lscoreutils 8.32(以及 glibc 2.28 和 kernel 4.11)的版本现在能够使用新的statx(2)系统调用(请参阅本答案的末尾)来提取创建时间元数据。

所以要列出文件已排序根据创建/出生日期/时间,您可以使用:

ls -lt --time=birth

-t选项将按选项指示的时间类型排序--time(I怀疑 birth如果愿意,可以更改creation)。

添加-r以反转排序顺序。

debugfs对于extN文件系统

debugfs -R 'stat partition/relative/path/to/file' /dev/sda1

你会得到类似的内容crtime不是 ctime!)如果你使用ext4.

 ctime: 0x513a50e5:d4e448f0 -- Fri Mar  8 21:58:13 2013
 atime: 0x513dd8f1:04df0b20 -- Mon Mar 11 14:15:29 2013
 mtime: 0x513a50e5:d4e448f0 -- Fri Mar  8 21:58:13 2013
crtime: 0x513a259a:35191a3c -- Fri Mar  8 18:53:30 2013

此命令可能需要一些时间才能返回,可能是因为它还列出了与文件相关的每个范围。

使用 VCS?

现在如果你想命令文件按创建日期排列,我想这不容易(也不正确)实现。作为吉尔斯说,如果您使用版本控制系统,可能会更容易。但你可以尝试看看ext4API...

命令stat(2021 年更新)

我在(最近的)Ubuntu 系统上的文件系统上尝试了该stat -c '%w' myfile命令,但没有成功(它只是回答)。ext4-

2021 年更新:根据托马斯·尼曼,如果您至少有 coreutils 8.31、glibc 2.28 和 kernel 4.11,则上述命令适用于 Linux。尽管您可以尝试,但它本身不会对文件进行排序:

stat -c '%w %n' * | sort -n 

为了实现这一点。%W如果您不关心人类可读的日期,请使用。添加-r选项以sort反转顺序。


2020 年更新:自 Linux 起内核4.11,一个新的statx(2)系统调用已被介绍。如果文件系统上有可用的信息,它的 API 可以访问文件创建时间。据我所知,还没有标准/稳定的用户空间实用程序允许我们获取此信息,但它可能会在一段时间内出现。这不是一个标准的 POSIX 接口,而是 Linux 特有的接口,说man:

statx() 在内核 4.11 中被添加到 Linux 中; glibc 2.28 中添加了库支持。

statx() 是 Linux 特定的。

答案3

在运行内核 4.11 或更高版本、glibc 2.28 或更高版本的 Linux 系统上,以及coreutils 8.31 或更高版本stat可以显示文件在存储该文件的文件系统上的诞生时间。ls -l可以通过以下方式获得类似于的输出

stat -c "%A %4h %U %G %10s %.16w %n" -- *

和排序输出(假设没有带有换行符的文件名)

stat -c "%.10W %A %4h %U %G %10s %.16w %n" -- * |
  sort -k1,1n |
  cut -d' ' -f2-

coreutils 8.32 或更高版本ls可以使用出生时间显示和排序,使用 --time=birth选项:

ls -l --time=birth

上面的调用stat使用这些格式选项:

  • %.10W:出生时间,自 Unix 纪元以来的秒数(带有 10 位小数部分)。
  • %A:文件类型和权限,ls -l格式
  • %4h:文件的硬链接数量,与四个字符对齐
  • %U: 所属用户的名称
  • %G: 所属组的名称
  • %10s:文件大小,对齐到十个字符
  • %.16w:出生时间,采用人类可读的格式,截断为十六个字符(足以显示年、月、日、小时、分钟和秒)
  • %n: 文件名

答案4

这是一个 Perl 脚本,它使用 Totor 的答案来实现你想要的(如果你的文件系统是 ext4)。

可以在我的家用机器(Ubuntu)和我的服务器(CentOS)上运行,但没有经过其他测试,所以 ymmv。

#!/usr/bin/env perl

use Modern::Perl '2009';

use DateTime;


# Open the current directory for reading
opendir my $dh, "." or die "Unable to open directory: $!";

# Create a hash to save results into
my %results;
my %datestamp;

# Loop through the directory getting creation date stats for each file
while ( my $filename = readdir $dh ) {
    # Skip non-files
    next if $filename eq '.' or $filename eq '..';

    # Save the ls output for this file/directory
    $results{ $filename } = `ls -ld $filename`;

    my $stats = `debugfs -R 'stat $filename' /dev/sda6 2>/dev/null`;
    # crtime: 0x51cd731c:926999ec -- Fri Jun 28 12:27:24 2013
    $stats =~ m/crtime\: \w+\:\w+ -- (.+?)\n/s;
    my $datestring = $1;

    # Dissect date with a regexp, ick
    my %months = (
        'Jan' => '1',
        'Feb' => '2',
        'Mar' => '3',
        'Apr' => '4',
        'May' => '5',
        'Jun' => '6',
        'Jul' => '7',
        'Aug' => '8',
        'Sep' => '9',
        'Oct' => '10',
        'Nov' => '11',
        'Dec' => '12',
    );
    $datestring =~ m/\w+ (\w+)  ?(\d+) (\d\d)\:(\d\d)\:(\d\d) (\d\d\d\d)/;

    # Convert date into a more useful format
    my $dt = DateTime->new(
        year   => $6,
        month  => $months{$1},
        day    => $2,
        hour   => $3,
        minute => $4,
        second => $5,
    );

    # Save the datestamp for this result
    $datestamp{ $filename } = $dt->iso8601;
}

# Output in date order
my @filenames = sort { $datestamp{$a} gt $datestamp{$b} } keys %datestamp;

foreach my $filename ( @filenames ) {
    print $results{ $filename };
}

相关内容