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


112

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

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



1
确实似乎是一种方式来获得该文件的创建时间在Linux中,如果该文件是一个ext4文件系统上。参见:unix.stackexchange.com/a/131347/182996
kaartic '18

Answers:


94

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

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

请注意,ctimels -lc不是文件创建时间,而是inode更改时间。每当有关文件的任何内容(内容或元数据)发生任何更改(除了仅在读取文件时ctime不会更新(即使atime已更新))时,inode更改时间都会更新。特别是,ctime总是比mtime(文件内容修改时间)更新,除非将mtime明确地设置为将来的日期。


1
Cygwin中ls -cls --help显示了-c-l和结合使用时的功能-lt
亚伦·马拉斯科

6
@Aaron不,ctime不是创建时间。纯粹基于“ ctime”和“ creation”以同一字母开头这一事实,这是一个常见的混淆,但是ctime和创建时间之间没有任何关系。我已经更新了答案,以解决这种困惑。
Gilles

大声笑我不好。我试图确认Ya的Cygwin部分(IIRC,您的原始帖子有可能的命令)。如果我已经注意的话,它的确会说“ ctime(文件状态信息的最后修改时间)”。
亚伦·马拉斯科

添加到@Gilles答案;我使用NFS 3.x文件服务器(不确定底层文件系统;虽然我猜是UFS,但它是UFS或ZFS)。在Redhat 6.x下:-U按创建时间排序。在Solaris 10.x中:/usr/bin/ls不支持-U/usr/ucb/ls支持-U和创建时间排序呢。这些结果显然取决于首先存储该信息的文件系统。
Brian Vandenberg 2012年

1
@ghoti如果目录中没有文件被删除(或移动/重命名/硬链接/…),则目录顺序是某些文件系统上的创建顺序,但不是全部。例如,在ext4上不是这样。我不知道在Solaris的UFS上是否如此。
吉尔斯

16

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

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

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

该命令可能需要一些时间才能返回,这可能是因为它还列出了与文件相关的每个扩展区。

现在,如果您想按创建日期排序文件,我想这是不容易的(也不正确的)。正如Gilles所说,如果使用修订控制系统,可能会更容易。但是您可以尝试看看ext4API ...

我在(足够近的)Ubuntu系统stat -c '%w' myfile上的ext4文件系统上尝试了该命令,但未成功(仅回答-)。


如果有人想要一个内胆:f='/path/to/file'; debugfs -R "stat $f" $(df $f|(read a; read a b; echo "$a"))|grep crtime
Boop

3

这是一个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 };
}

还要指出的是,某些文件可能具有记录创建日期/时间的元数据(例如exif)。例如,如果您的所有文件碰巧都是数码照片,则很可能具有此数据。这是使用perl的Image :: ExifTool示例
乔纳森·克罗斯

0

使用此命令ls -lct按创建日期对文件排序。


2
是的,这不是“正确的”命令,但是在大多数情况下,这是您要查找的内容
madnight

有没有办法用“查找”来做到这一点,以便它以这种方式打印子目录中的所有文件?
Colin D

ctime是改变的时候,而不是创建时间。
Nabi KAZ
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.