Greetings from chilly, snowy Buffalo (NY, USA). I spent about 6 years doing no programming at all and now I'm using perl again. I am still hooked on it. So this week I started exploring CPAN modules that give info about and, in some cases, modify, the filesystem. I know of 3 modules that are used for that: the core module File::Spec, the module Path::Class (used it and liked it, a while back), and the module Path::Tiny. This meditation focuses on Path::Tiny, which seems to be stalking me. I see a lot of module authors using it in their code (that is, it has become a common dependency).

Path::Tiny is probably a bit of a misnomer. It has many methods. Many many. What I was most interested in this week was the method tempdir. Something about how tempdir works took me by surprise (yes, I am finally getting around to the point of this meditation :). The method returns a {normalized, right-slashed, absolute} pathname, but it also creates the temporary directory. Maybe I am odd, but I expected to be given a string and then create the directory with that pathname myself!

Below, some code (playful deliberately) that uses tempdir and will demonstrate that when tempdir is called, a directory is created.

#!/usr/bin/env perl # Last modified: Wed Dec 04 2024 10:48:30 PM -05:00 [EST] use strict; use v5.18; use utf8; use warnings; =head1 NAME pathology.pl =cut use Term::ReadKey qw/ReadMode ReadKey/; use File::Spec; use Path::Tiny; my $user; sub versions { say $File::Spec::VERSION, q[ ] , $Path::Tiny::VERSION ; } sub who { no warnings 'deprecated', 'experimental'; use Config; given (lc( $Config{osname} )) { when ('linux') { $user = $ENV{USER} } when ('cygwin') { $user = $ENV{USER} } when ('mswin32') { $user = $ENV{USERNAME} } default { say "osname is something we don't know, " +, "we'll guess it's something Unixy, so +" , "let's say that user name is " , getlogin || "null"; $user = getlogin; } } return $user; } # ------------------------------------------------------------- # # For all its wealth of methods, I found no direct equivalent of # "tmpdir" in Path::Tiny, so I use File::Spec's. say "We use " , File::Spec->tmpdir , " for temporary files."; # ------------------------------------------------------------- # say "We are currently in directory " , Path::Tiny->cwd; say "Our filesystem is rooted at " , Path::Tiny->rootdir; say "Aha, " , who() , ", we may have a temp dir for you!"; my $tadah = Path::Tiny->tempdir(TEMPLATE => "${user}-XXXXXXXX"); say "Maybe we have made a temp directory at " , $tadah , ", let's see: +"; if ( -e $tadah and -d $tadah ) { say "'$tadah' already exists and is a directory."; say "Type 'y' if you wish to remove this directory:"; ReadMode 'cbreak'; my $reply = ReadKey(0); ReadMode 'normal'; if (lc $reply eq "y") { print "Ok, we are going to attempt to remove it now ..." ; rmdir($tadah) and say "Success." or say "BAH! Could not remove it, reason: $!"; } else { say "Ok, leaving $tadah alone."; } } else { mkdir($tadah => 0777) and say "created temp dir." or die "We couldn't make a directory \"$tad +ah\"", $!; sleep 6; rmdir($tadah) and say "$tadah removed." }
Dec 05, 2024 at 04:07 UTC
Examine what is said, not who speaks.
Love the truth but pardon error.
Silence betokens consent.
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re: Temp directories and the surprise creation thereof
by choroba (Cardinal) on Dec 05, 2024 at 08:56 UTC
    > The method returns a {normalized, right-slashed, absolute} pathname, but it also creates the temporary directory. Maybe I am odd, but I expected to be given a string and then create the directory with that pathname myself!

    The behaviour is documented under tempfile, tempdir, albeit in the style I don't like: it just tells you to read the documentation of something else:

    tempdir is just like tempfile, except it calls File::Temp->newdir instead.

    And if we follow the link to File::Temp::newdir, we can read:

    Create a temporary directory using an object oriented interface.

    Careful reading of both the documents is needed to understand all the details. If your program is security sensitive, read the notes on security and understand them.

    Update: added a link to the quoted documentation.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

      Very kind of you to comment on my meditation, choroba, and I agree that using a reference to the documentation of another module isn't optimal. Your (gentle, implicit) criticism that I didn't follow the link is righteous and deserved. I'd make a poor Moria-dwarf: sometimes side passageways hold the best treasure ;-).

      Dec 05, 2024 at 17:46 UTC
        Well, I crossed "the link" because there's no link to File::Temp anywhere in the documentation. So it was rather a criticism of the documentation's author than the reader.

        Update: Now I've realised there was no link to Path::Tiny in my reply. Going to fix it.

        map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]