Molti moduli Perl sono, almeno da me, dati per scontati, nel senso che si utilizzano così di frequente che ormai sono come parte del linguaggio stesso. In realtà si tratta di interessanti progetti per semplificare le attività di ogni giorno, per i quali è opportuno scrivere qualche riga non solamente “celebrativa”, ma utile a chi non li conoscesse.

Uno di questi moduli è Path::Class, di Ken Williams, utilizzato per la gestione dei file utilizzati da un’applicazione. Esso offre alcuni vantaggi rispetto alle funzioni core di Perl:

  • Un’unica API object-oriented per gestire file e directory
  • Path multipiattaforma - non serve più preoccuparsi del fatto che in Unix venga utilizzato lo slash (/) e sotto Windows il backslash (\) (grazie a File::Spec)
  • Metodi che semplificano lettura/scrittura di file
  • Metodi che semplificano l’attraversamento di un albero di directory
  • Vari altri metodi utili (ad esempio per capire se una directory si trova dentro un’altra)

Utilizzare Path::Class, è molto semplice. Ad esempio, per rappresentare una directory in maniera platfrom-independent possiamo scrivere:

use Path::Class;

my $dir_foto = dir('documenti', 'michele', 'foto');

Il path verrà creato con i separatori adatti al sistema operativo in cui ci si trova. In altre parole, Path::Class farà “la cosa giusta”. La rappresentazione in stringa dell’oggetto creata contiene tale path, pertanto l’oggetto è utilizzabile ovunque sia richiesta una stringa come path o nome file. Ad esempio è perfettamente lecito scrivere:

use Path::Class;

my $pic = dir('documenti', 'michele', 'foto', 'img0002.jpg');
open (my $fh, '<', $pic) or die $!;
# Operazioni di lettura a piacere
close $fh;

In realtà, l’apertura del file (in questo caso in lettura) può essere effettuata anche più semplicemente:

my $fh = $pic->openr();

Questa soluzione ha anche il vantaggio di ritornare un oggetto di tipo `IO::File` anziché un filehandle normale. Se l'intenzione è invece quella di leggere l'intero file, basta un:

my $data = $pic->slurp();

Tornando alle directory, possiamo facilmente iterare sui file di una:

while (my $pic = $dir_foto->next) {
    say $pic->basename;
}

O anche attraversare un albero ricorsivamente:

$dir_foto->recurse(
    depthfirst => 0,
    preorder   => 1,
    callback   => sub {
        my ($file) = @_;
        say 'È una foto in JPEG' if $file->basename ~~ m/jpg/xmsi;
    }
)

Semplicissimo!