打开目录并按创建日期对文件进行排序

时间:2013-04-19 01:23:33

标签: perl file sorting

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

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

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

do things with @files...

CPAN在sort命令上有一个页面,但我无法访问它,我在页面上找不到“date”或“creation”字样。

为了回应编辑,我应该说我使用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";
}

5 个答案:

答案 0 :(得分:11)

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

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

因此,默认排序sort @numbers相当于sort {$a <=> $b} @numbers

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

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

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

答案 1 :(得分:2)

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

答案 2 :(得分:2)

  

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

你做不到。 创建时间根本不存在。 * nix跟踪了三个时间元素,如操作系统:

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

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

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

即使在具有文件创建时间的Windows上,也无法真正跟踪文件创建。它只跟踪创建目录条目的时间,这类似于ctime的作用。而且,您甚至可以通过Windows API修改此创建时间。我怀疑Mac的文件创建时间是HFS文件系统的遗留物,并且实际上并没有指向文件创建时间和首次创建目录条目的时间。


正如其他人所指出的那样。您可以在排序例程中添加一段代码,说明您希望如何排序。这是一个简单的例子。注意我使用File::stat,它为旧的stat命令提供了一个很好的按名称​​接口。如果我使用旧的 stat 命令,我会得到一个数组,然后必须找出数组中我想要的项目所在的位置。在这里,stat命令为我提供了一个 stat 对象,我可以使用mtimeatimectime 方法< / em>用于抽出正确的时间。

我还使用<=>,它是专门为sort命令块设置的比较运算符。

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";
}

答案 3 :(得分:0)

#!/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更改时间(不是创建时间)。

答案 4 :(得分: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;