Today we will focus on a simple task: listing the files contained in a directory, sort them by modification time (mtime
) and display the result in a JSON array.
We are gonna use Mojo::File
for the file system part and Mojolicious::Lite
to expose those data on a simple but effective JSON API.
Prerequisites
apt install libmojolicious-perl
touch mtime.pl && chmod +x mtime.pl
The code
Our lite application is separated in two main parts:
- a helper, the
get_paths_by_ctime()
method - an unique route that returns an array reference containing our file list
#!/usr/bin/env perl
# Automagically import Mojo::Base -base
use Mojolicious::Lite -signatures;
use Mojo::File 'path';
helper get_paths_by_mtime => sub {
my $files_list = path( '/tmp' )->list;
# Returns an array of Mojo::File
my @files = sort { $a->stat->mtime <=> $b->stat->mtime }
map { $_ } $files_list->each;
# Returns an array of paths sorted by modification date
return map { $_->realpath->to_string } @files;
};
get '/' => sub( $c ) {
$c->render( json => \$c->app->get_paths_by_mtime );
};
app->start;
Starting the app
Mojolicious comes with the morbo
HTTP and WebSocket development server
morbo mtime.pl
Server available at http://127.0.0.1:3000
If you visit this adress in your browser, it should display the list of files contained in the /tmp
directory of your computer. On mine it returns:
[
"/tmp/sddm-:0-RweLaZ",
"/tmp/xauth-1000-_0",
"/tmp/cpan_install_3QQI.txt",
"/tmp/!home!sfeu!.emacs.d!savefile!ido.hist~",
"/tmp/!home!sfeu!.emacs.d!savefile!recentf~",
"/tmp/!home!sfeu!dev!processing-perl!etc!crontab~",
"/tmp/!home!sfeu!.emacs.d!personal!custom.el~",
"/tmp/!home!sfeu!dev!processing!.env~",
"/tmp/liste_desabonnement_20200218.csv",
"/tmp/!home!sfeu!dev!processing!.git!COMMIT_EDITMSG~",
"/tmp/!home!sfeu!scripts!mtime.pl~"
]
It is just a bunch of temporary files, mostly those I edit in my text editor. Note that the directories and special files (.
, ..
) are not listed.
Releasing the power of Mojo::File
Retrieving a list of files
Mojolicious provide a lot of utilities that makes your Perl programmer life almost bearable. Note that Mojolicious needs zero dependencies, this is the reason it comes with a great toolkit for doing simple tasks. Mojo::File
is one of those. Let's see how to use it.
use Mojo::File 'path';
By using Mojo::File
and loading it's path function, you will be able to construct a Mojo::File
object by passing it any kind of path:
my $files_list = path( '/tmp' )->list;
The list
method called on a Mojo::File
directory will return all files contained in this directory. The returned object is a Mojo::Collection
object, an array-based container for collections.
Sorting the objects by modification date
To read the following code, start by the end.
my @files = sort {
$a->stat->mtime <=> $b->stat->mtime
} $files_list->each;
- first, you return all the elements of the collection by using
each
- it will return an array, that can be passed to
sort
sort
is being passed a comparison function. In our case we will compare by mtime
(modification time). The reason we can access to mtime
from the array of Mojo::File
s is that this module got it's own stat
method that returns itself a File::stat
object for the path. This is where the magic happend!
Retrieving the files paths
By using a simple map
function and the Mojo::File
chainedrealpath->to_string
methods we will transform our array of objects to a simple array of strings:
return map { $_->realpath->to_string } @files;
The route
The result of our helper is then rendered as JSON (must be passed to the front as an arrayref
).
Making it even more concise
Marcus Ramberg explained me how to make this even more concise by using Mojo::Collection->sort
The helper can be rewritten:
helper get_paths_by_mtime => sub {
return path( '/tmp' )->list
->sort( sub { $a->stat->mtime <=> $b->stat->mtime })
->map('realpath');
};
Conclusion
The conciseness and readability of this program is quite surprising thanks to the effective tools used.
I hope you enjoyed reading this presentation and that it gave you the wish to use the formidable Mojolicious framework and it's utilities.
Acknowledgments
Thanks to Marcus Ramberg who read this, improved and simplified the code.
Top comments (2)
This is some very clean and expressive modern Perl, and the use of Mojo is outstanding.
I also really enjoy a lot of the ancillary modules which come with mojo, such as
Mojo::Collection
,Mojo::File
, and of course the user agent.Thank you so much for sharing.
Thanks for the encouragement. This is a great warmup in my heart.