8

我需要在创建文件时打开目录并对其进行排序。我可以找到一些讨论,使用 Perl、排序和文件的标签,根据修改日期对文件进行排序。我认为这是比按创建日期排序更常见的需求。我使用 Perl。以前有一些关于 Perl 以外的其他语言(例如 php 或 java)按创建日期排序的帖子。

例如,我需要执行以下操作:

opendir(DIR, $ARGV[0]);                             
my @files = "sort-by-date-created" (readdir(DIR)); 
closedir(DIR);

do things with @files...

CPAN 有一个关于排序命令的页面,但对我来说不是很容易访问,而且我在页面上找不到“日期”或“创建”字样。

作为对编辑的回应,我应该说我使用的是 Mac,OS 10.7。我知道在 Finder 中,有一个按创建日期排序的选项,因此必须有某种指示以某种方式附加到该系统中的文件的创建日期。

作为对答案的回应,这里是尝试对文件进行排序的脚本的另一个版本:

#!/usr/bin/perl
use strict; use warnings;

use File::stat; # helps with sorting files by ctime, the inode date that hopefully can serve as creation date

my $usage = "usage: enter name of directory to be scanned for SNP containing lines\n";
die $usage unless @ARGV == 1;

opendir(DIR, $ARGV[0]);                             #open directory for getting file list
#my @files = (readdir(DIR));
my @file_list = grep ! /^\./, readdir DIR; 
closedir(DIR);  

print scalar @file_list."\n";

for my $file (sort {
        my $a_stat = stat($a);
        my $b_stat = stat($b);
        $a_stat->mtime <=> $b_stat->mtime;
    }  @file_list ) {
    say "$file";
}
4

5 回答 5

13

您可以通过向排序函数提供子例程或代码块来自定义排序顺序。

  • 在这个子块或块中,您需要使用特殊变量$a$b,它们表示比较 @array 中的值。
  • sub 或 block 需要返回一个小于、等于或大于的值0来指示$a是小于、等于还是大于$b(分别)。
  • 您可以使用特殊的比较运算符(<=>用于数字、cmp字符串)为您执行此操作。

所以默认排序sort @numbers等价于sort {$a <=> $b} @numbers.

在按创建时间排序的情况下,您可以使用stat函数来获取有关文件的信息。它返回有关文件的一系列信息,其中一些可能不适用于您的平台。文件的最后修改时间通常是安全的,但创建时间不是。(它返回的ctime第 11 个值)尽可能接近(它表示 *nix 上的 inode 更改时间,win32 上的创建时间),它表示为自 epoch 以来的秒数,这很方便,因为它意味着你可以做一个简单的数字排序。

my @files = sort {(stat $a)[10] <=> (stat $b)[10]} readdir($dh);

我不确定您是否也想过滤掉目录。如果是这种情况,您可能还想使用grep.

于 2013-04-19T01:49:29.163 回答
3

我需要在创建文件时打开目录并对文件进行排序。

你不能。创建时间根本不存在。*nix 类操作系统跟踪三个时间元素:

  • mtime:这是文件最后一次修改的时间。
  • atime:这是上次访问文件的时间。
  • ctime:这是上次修改inode的时间。

在 Unix 中,某些文件信息存储在inode中。这包括您在获取文件的 Perl 时看到的各种内容stat。这是用户的名称、文件的大小、它所在的设备、链接数,以及具有讽刺意味的是mtimeatimectime时间戳。

为什么没有创建时间?因为你会如何定义它?如果我移动文件怎么办?如果有新的创建时间(顺便说一句,ctime不会随着移动而改变)。如果我复制文件怎么办?新副本是否应该有新的创建时间?如果我做了一个副本,然后删除了原件怎么办?如果我编辑了一个文件怎么办?如果我用我的编辑更改了文件中的所有内容呢?还是我编辑了文件,然后将其重命名为全新的名称?

即使在具有文件创建时间的 Windows 上,也不会真正跟踪文件的创建。它仅跟踪创建目录条目的时间,这有点ctime像。而且,您甚至可以通过 Windows API修改此创建时间。我怀疑 Mac 的文件创建时间是 HFS 文件系统的遗物,实际上并没有像首次创建目录条目的时间那样指向文件创建时间。


正如其他人指出的那样。您可以在排序例程中添加一段代码,说明您希望如何排序。这是一个快速的例子。注意我使用File::stat它为我提供了旧命令的良好名称接口。stat如果我使用旧的stat命令,我会得到一个数组,然后必须找出我想要的项目在数组中的位置。在这里,stat命令给了我一个stat对象,我可以使用mtime, atime, 或ctime 方法来提取正确的时间。

我还使用which 是专门为命令块<=>制作的比较运算符。sort

排序命令给你两个项目$a$b。您使用这两个项目来确定您想要什么,然后使用或者<=>cmp是否$a更大,$b更大,或者它们的尺寸相同。

#! /usr/bin/env perl

use 5.12.0;
use warnings;

use File::stat;

my $dir_name = shift;

if ( not defined $dir_name ) {
    die qq(Usage: $0 <directory>);
}

opendir(my $dir_fh, $dir_name);

my @file_list;
while ( my $file = readdir $dir_fh) {
    if ( $file !~ /^\./ ) {
        push @file_list, "$dir_name/$file"
    }
}
closedir $dir_fh;

say scalar @file_list;

for my $file (sort {
        my $a_stat = stat($a);
        my $b_stat = stat($b);
        $a_stat->ctime <=> $b_stat->ctime;
    }  @file_list ) {
    say "$file";
}
于 2013-04-19T03:07:30.463 回答
2

OS X 将创建日期存储在 Mac 特定的元数据中,因此标准 Perl 文件系统函数不知道它。您可以使用MacOSX::File模块来访问此信息。

于 2013-04-19T01:43:46.663 回答
1
#!/usr/bin/env perl
use strict;
use warnings;
opendir(DIR, $ARGV[0]);
chdir($ARGV[0]);
my @files = sort { (stat($a))[10] <=> (stat($b))[10] } (readdir(DIR));
closedir(DIR);
print join("\n",@files);

stat为您提供文件的各种状态信息。其中字段 10 是 ctime(在支持它的文件系统上),它是 inode 更改时间(不是创建时间)。

于 2013-04-19T01:30:17.673 回答
0

Mojo::File带来了一些有趣且可读的方法来做到这一点。

#!/usr/bin/env perl
use Mojo::File 'path';

my $files_list = path( '/whatever/dir/path/' )->list;

# Returns an array of Mojo::File
my @files = sort { $a->stat->ctime <=> $b->stat->ctime }
  map { $_ }  $files_list->each;

# Returns an array of paths sorted by modification date (if needed)
my @paths = map { $_->realpath->to_string } @files;
于 2020-02-17T17:29:42.223 回答