Open a directory and sort files by date created
You can customize the sorting order by providing a subroutine or code block to the sort function.
- In this sub or block, you need to use the special variables
$a
and$b
, which represent the values from the @array as they are compared. - The sub or block needs to return a value less than, equal to, or greater than
0
to indicate whether$a
is less than, equal to, or greater than$b
(respectively). - You may use the special comparison operators (
<=>
for numbers,cmp
for strings) to do this for you.
So the default sort sort @numbers
is equivalent to sort {$a <=> $b} @numbers
.
In the case of sorting by creation time, you can use the stat function to get that information about the file. It returns an array of information about the file, some of which may not be applicable to your platform. Last modification time of the file is generally safe, but creation time is not. The ctime
(11th value that it returns) is as close as you can get (it represents inode change time on *nix, creation time on win32), which is expressed as the number of seconds since the epoch, which is convenient because it means you can do a simple numeric sort.
my @files = sort {(stat $a)[10] <=> (stat $b)[10]} readdir($dh);
I'm not sure if you want to filter out the directories also. If that is the case, you'll probably also want to use grep
.
I need to open directories and sort the files by the time they were created.
You can't. The creation time simply does not exist. There are three time elements tracked by *nix like operating systems:
- mtime: This is the time the file was last modified.
- atime: This is the time the file was last accessed.
- ctime: This is the time when the inode was last modified.
In Unix, certain file information is stored in the inode. This includes the various things you see when you take the Perl stat
of a file. This is the name of the user, the size of the file, the device it's on, the link count, and ironically, the mtime, atime, and ctime timestamps.
Why no creation time? Because how would you define it? What if I move a file? Should there be a new creation time (By the way, ctime won't change with a move). What if I copy the file? Should the new copy have a new creation time? What if I did a copy, then deleted the original? What if I edited a file? How about if I changed everything in the file with my edit? Or I edited the file, then renamed it to a completely new name?
Even on Windows that has a file creation time, doesn't really track the file creation. It merely tracks when the directory entry was created which is sort of what ctime
does. And, you can even modify this creation time via the Windows API. I suspect that the Mac's file creation time is a relic of the HFS file system, and really doesn't point to a file creation time as much as the time the directory entry was first created.
As others have pointed out. You can add into the sort routine a block of code stating how you want something sorted. Here's a quickie example. Note I use File::stat which gives me a nice by name interface to the old stat
command. If I used the old stat command, I would get an array, and then have to figure out where in the array the item I want is located. Here, the stat
command gives me a stat object, and I can use the mtime
, atime
, or ctime
method for pulling out the right time.
I also use the <=>
which is a comparison operator specifically made for the sort
command block.
The sort command gives you two items $a
and $b
. You use these two items to figure out what you want, adn then use either <=>
or cmp
to say whether $a
is bigger, $b
is bigger, or they're both the same size.
#! /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";
}
OS X stores the creation date in Mac-specific metadata, so the standard Perl filesystem functions don't know about it. You can use the MacOSX::File module to access this information.