Module:...ic::File(3)

๐Ÿ“ฆ version 1.1.3, in alpine 3.24

๐Ÿ’– NAME ๐Ÿ’–

So this is the perl manpage for Module::Generic::File โ€” File Object Abstraction Class โœจ like, the whole vibe is "objects that represent files and directories, but make it glamorous".


๐Ÿฆ‹ SYNOPSIS ๐Ÿฆ‹

Okay bestie, here's the whole mood board, copy it exactly, no cap:

use Module::Generic::File qw( cwd file rootdir tempfile tempdir sys_tmpdir stdin stderr stdout );
my $f = Module::Generic::File->new( '/some/file' );
$f->append( "some data" );
$f->open && $f->write( "some data" );
my $d = file( "/my/directory/somewhere" );
$d->makepath;
$d->chdir;
$d->contains( $f );
my $d = file( $tmpdir )->mkpath->first;
$f->is_part_of( $d );
$f->touchpath;
my $f = $d->child( "file.txt" )->touch;
$f->code == 201 && say "Created!";
say "File is empty" if( $f->is_empty );

my $file = tempfile();
my $dir  = tempdir();

my $tmpname = $f->tmpname( suffix => '.txt' );
my $f2 = $f->abs( $tmpname );
my $sys_tmpdir = $f->sys_tmpdir;
my $f3 = $f2->move( $sys_tmpdir )->touch;
my $io = $f->open;
say "Can read" if( $f->can_read );
say "Can write" if( $f->can_write );
say "Can execute" if( $f->can_exec );
$f->close if( $f->opened );
say "File is ", $f->length, " bytes big.";

my $f = tempfile({ suffix => '.txt', auto_remove => 0 })->move( sys_tmpdir() );
$f->open( '+>', { binmode => 'utf8' } );
$f->seek(0,0);
$f->truncate($f->tell);
$f->append( <<EOT );
Mignonne, allons voir si la rose
Qui ce matin avoit desclose
Sa robe de pourpre au Soleil,
A point perdu cette vesprรฉe
Les plis de sa robe pourprรฉe,
Et son teint au vostre pareil.
EOT
my $digest = $f->digest( 'sha256' );
$f->close;
say $f->extension->length; # 3
# Enable cleanup, auto removing temporary file during perl cleanup phase

$file->utime( time(), time() );
# or to set the access and modification time to current time:
$file->utime;

# Create a file object in a different OS than yours
my $f = file( q{C:\Documents\Some\File.pdf}, os => 'Win32' );
$f->parent; # C:\Documents\Some
$f->filnema; # C:\Documents\Some\File.pdf

# Get URI:
my $u = $f->uri;
say $u; # file:///Documents/Some/File.pdf

# Enable globbing globally for all future objects:
$Module::Generic::File::GLOBBING = 1;
# or by object:
my $f = file( "~john/some/where/file.txt", { globbing => 1 } );

my $d = file( './some/where' );
my @files = $d->glob( '*.pl' );
die( "Something went wrong: ", $d->error ) if( !@files && $d->error );
my $last_file = $d->glob( '*.pl' ) ||
die( "Something went wrong: ", $d->error ) if( !defined( $last_file ) );
my @all = $d->glob( '*.pl', {
    brace => 1,
    expand => 1,
    no_case => 1,
    no_magic => 1,
    sort => 1,
});
$d->open || die( $d->error );
my @files = $d->read;

my $data = $file->load_perl || die( $file->error );
$file->unload_perl( $data, { indent => 4, max_binary_size => 1024, max_width => 60 } ) ||
    die( $file->error );

$file->flock(1) || die( $file->error );
my $new_object = $file->realpath;
my $new_object = Module::Generic::File->realpath( "/some/where/file.txt" );

my $file = Module::Generic::File->new("data.csv");

# Load CSV data
my $data = $file->load_csv(
    headers => 'auto',
    binmode => 'utf-8',
    expects => 'array',
    # Passing along a Text::CSV option
    sep_char   => ',',
    quote_char => '"',
) || die( $file->error );

# Unload CSV data
$file->unload_csv(
    $data,
    headers      => 'auto',
    # Passing along a Text::CSV option
    sep_char     => ',',
    binmode      => 'utf-8',
    always_quote => 1,
) || die( $file->error );

Yeah it's a lot. It's iconic though. ๐Ÿ’…


๐ŸŽ€ VERSION ๐ŸŽ€

v0.15.0


๐ŸŒธ DESCRIPTION ๐ŸŒธ

So this package? It provides a comprehensive and versatile set of methods and functions to manipulate files and directories. Like, the whole toolkit, bestie. ๐Ÿงฐโœจ

But here's the unique feature that literally makes it not like every other file module: you can work with files in a different operating system context, using the "os" parameter. Say your environment is a unix flavoured operating system โ€” you can still do this, no cap:

use Module::Generic::File qw( file );
my $f = file( q{C:\Documents\Newsletters\Summer2018.pdf}, os => 'win32' );
$f->parent; # C:\Documents\Newsletters

And then โ€” plot twist โ€” switch to old Mac format:

my $f2 = $f->as( 'mac' );
say $f2; # Documents:Newsletters:Summer2018.pdf

Main character energy honestly. ๐Ÿ˜ญ


โœจ METHODS โœจ

๐Ÿซถ new

Takes a file as its first parameter โ€” and bestie, whether the file actually exists or not is totally ok. This instantiates an object that you then use to access all the other key methods. It also takes these optional parameters:

  • "autoflush" โ€” Enables or disables autoflush. Takes a boolean value and defaults to true.
  • "auto_remove" โ€” Takes a boolean value. Automatically removes the temporary directory or file when the object is cleaned up by perl. ๐Ÿงน
  • "base_dir" โ€” Sets the base directory for this file. If none is provided, it will attempt to get the current working directory, and if it cannot find it โ€” most likely because it has been removed while your perl script was running ๐Ÿ˜ญ โ€” then it will try to "chdir" to the system temporary directory, and if that, too, fails, it will set an error return "undef".
  • "base_file" โ€” Sets the base file for this file, i.e. the reference file from which the base directory will be derived, if not already specified.
  • "collapse" โ€” Enables or disables the collapsing of dots in the file path. This will attempt to resolve and remove the dots to provide an absolute file path without dots. For example, "/../a/b/../c/./d.html" would become "/a/c/d.html" ๐Ÿช„
  • "globbing" โ€” Boolean value, by default set to the value of the package variable $GLOBBING, which itself is false by default. If enabled, this will allow "resolve" to do globbing on the filename, so that any shell meta characters are resolved. For example "~joe/some/file.txt" would be resolved to "/home/joe/some/file.txt". Otherwise the filename would remain "~joe/some/file.txt". This is useful when you have filename with meta characters in their file path, like "/some/where/A [A-12] file.pdf". See also "globbing" to change the parameter for the current object, and also the "glob" and "resolve" methods.
  • "max_recursion" โ€” Sets the maximum recursion allowed. Defaults to 12. Its value is used in "mkpath" and "resolve".
  • "os" โ€” If provided, this tells Module::Generic::File to treat this new file as belonging to the specified operating system. This makes it possible to manipulate files or directories as if under a different system than the one you are currently using. ๐Ÿ–ฅ๏ธ๐Ÿฆ‹ Look also at "as" to change a file to make it suitable for a different OS, such as "Mac", "Win32", "dos", "Linux", etc.
  • "resolved" โ€” A boolean flag which states whether this file has been resolved already or not.
  • "type" โ€” The type of file this is. Either a file or a directory.

๐ŸŽ€ abs

If no argument is provided, this returns the current object, since the underlying file is already changed into absolute file path.

If a file path is provided, then it will change it into an absolute one and return a new Module::Generic::File object. ๐Ÿซถ

โญ absolute

This is a convenient alias to "abs". Same energy, shorter name. ๐Ÿ’…

๐Ÿ”ฅ append

Provided with some data as its first argument, and assuming the underlying file is a file and not a directory, this will open it if it is not already opened and append the data provided.

If the file was already opened, whatever position you were in the file will be restored after having appended the data. Considerate queen. ๐Ÿ‘‘

It returns the current file object upon success for chaining, or undef and sets an error object if an error occurred.

๐ŸŒˆ as

Provided with an "OS" name, and this returns a filename with a format suitable for that operating system, notwithstanding the one you are currently using. ๐Ÿฆ‹

๐Ÿ“ atime

This is a shortcut to "atime" in Module::Generic::Finfo.

๐Ÿงš auto_remove

This takes a boolean value and enables or disables the auto remove of temporary file or directory created by this module upon perl cleanup phase.

๐Ÿ’œ autoflush

This takes a boolean value and enables or disables the auto flush.

๐ŸŒธ base_dir

This sets the base directory of reference for this file object.

๐ŸŽ€ base_file

This sets the base file of reference for this file object.

โœจ baseinfo

This returns a list containing:

  1. the file base name
  2. the file directory path
  3. the file suffix if the file is a file, or an empty string if this is a directory

In scalar context, it returns the file base name as a Module::Generic::Scalar object.

This method accepts as an optional parameter a list or an array reference of possible extensions. ๐Ÿ’ซ

๐Ÿฆ‹ basename

This returns the file base name as a Module::Generic::Scalar object.

You can provide optionally a list or array reference of possible extensions or regular expressions. Look:

my $f = Module::Generic::File->new( "/some/where/my/file.txt" );
my $base = $f->basename( [qw( .zip .txt .pl )] ); # returns "file"
my $base = $f->basename( qr/\.(.*?)$/ ); # returns "file"

Obsessed with how clean that is. ๐Ÿ’…

๐Ÿซถ binmode

Sets or gets the file binmode.

๐ŸŒŸ block_size

This is a shortcut to "block_size" in Module::Generic::Finfo.

๐Ÿ’€ blocking

Turns on or off blocking or non-blocking io for file opened.

๐ŸŒˆ blocks

This is a shortcut to "blocks" in Module::Generic::Finfo.

๐Ÿ“ can_append

Returns true if the file or directory are writable, and data can be added to it. False otherwise.

If an error occurred, undef will be returned and an exception will be set. โš ๏ธ

โญ can_exec

This is an alias for "can_exec" in Module::Generic::Finfo.

๐ŸŽ€ can_read

Returns true if the file or directory are readable. False otherwise.

If an error occurred, undef will be returned and an exception will be set. โš ๏ธ

๐Ÿ’œ can_write

Returns true if the file or directory are writable. False otherwise.

If an error occurred, undef will be returned and an exception will be set. โš ๏ธ

๐Ÿฆ‹ canonpath

Takes an optional parameter representing the name of the operating system for which to canonise this file path. If no operating system name is provided, this will revert to $^O. See perlvar for more information about this variable.

Returns the canon path of the file object based on the operating system specified. ๐Ÿ—บ๏ธ

๐ŸŒธ changed

Returns true if the file was changed, false otherwise.


โ€ฆand we are literally just getting started, bestie, do not close this tab ๐Ÿ”ฅ

chdir ๐Ÿš

So if your file object is actually a directory, this is gonna try to chdir (as in chdir in perlfunc) into it. Like, actually move you there bestie, fr fr.

It hands back the current file object on success, or undef and sets an exception object if something went sideways.

child ๐ŸŽ€

Ok so this one has to be called on a directory object, mkay? Call it with a file name (and not a full path, like, just the name), and it'll give you back a brand-new file object built from the directory path plus the file you specified. Combo meal energy ๐Ÿ“.

chmod ๐Ÿ’…

Feed it an octal value, or a human file mode like a+rw, and it'll try to set the file or directory mode to match. Iconic.

Returns the current object on success, or undef and sets an exception object if it errored out.

chown ๐Ÿ‘‘

Give it a uid and a gid and it'll call chown in perlfunc on the underlying directory or file.

Both uid and gid are required โ€” no half-sending bestie โ€” but you can pass a value of -1 to tell perl you don't wanna change that one.

It returns true if the file or directory was changed, or 0 otherwise. (ngl the page literally writes o there, typo era ๐Ÿ’€, but you get the vibe)

If an error happened, it sets an error and returns undef.

See perlport for chown portability limitations โ€” it's giving "your mileage may vary by platform" ๐Ÿ˜ญ

cleanup ๐Ÿงน

This is just an alias for auto_remove. It enables or disables the auto cleanup of a temporary file or directory during the perl cleanup phase.

$tmp->cleanup(1); # Enable it
my $bool = $tmp->cleanup;

close ๐Ÿšช

Closes the underlying file or directory.

Returns the current object โ€” or, like, the object itself if no handle is even open. Either way you get the object back, iconic consistency.

code ๐Ÿ”ข

Sets or gets the http-equivalent 3-digits code describing the status of the underlying directory or file. Very "HTTP status but make it a file" of it.

If you pass a value, it sets the code. If you pass nothing, it'll guess the code based on the file's readability, existence, etc. Detective behaviour โœจ.

collapse_dots ๐ŸŒธ

In line with section 5.2.4 of the rfc 33986, this will flatten (i.e. remove) any dots that may be hanging out in the element file path. Bye dots ๐Ÿ‘‹.

It takes an optional list or hash reference of parameters, including separator, which is used as the directory separator. If you don't provide it, it'll revert to the default value for the current system.

contains ๐Ÿ“ฆ

This one can only be called on a directory object, and you hand it a file or a file object.

It returns true if the file is contained within the directory. Very "are you in the club or not" ๐Ÿซถ.

content ๐Ÿ“

Returns the content of the directory or file as a Module::Generic::Array.

If it's a directory, you get a Module::Generic::Array object with all the files inside that directory โ€” excluding . and .., and only within that directory. So like, not recursive, bestie. One layer, that's it.

If it's a regular file, you get its content as a Module::Generic::Array object.

If an error occurred, it returns undef and sets an exception object.

content_objects ๐Ÿฆ‹

This one works exclusively on directory objects โ€” try it on literally anything else and it returns undef and sets an error. Read the room ๐Ÿ’€.

It returns an array object of file objects.

Do not use this on a directory containing a very large number of items, for obvious reasons. Like, it will simply not slay. ๐Ÿ˜ญ

copy ๐Ÿ“‹

Takes a destination and attempts to copy itself over to it.

If the object represents a directory and the destination exists and is also a directory, it will copy the directory below the destination:

my $d = Module::Generic::File->new( "my/other_directory" );
my $new = $d->copy( "./another/directory" );
# $new now represents ./another/directory/other_directory

And of course, if the destination is a regular file, undef is returned and an exception is set. Rude but fair.

If the object represents a file and the destination exists, it'll copy the file under the target directory if the destination is a directory, or replace the target regular file if the destination is a regular file.

If the object file/directory doesn't actually exist, this merely changes virtually its file path. Vibes-only move โœจ.

This method, just like move, relies on File::Copy โ€” which means you can use a GLOB as the destination if you want. See the File::Copy documentation for more on that.

It returns a new Module::Generic::File object representing the new file path.

Note: you can also use the shortcut cp instead of copy โ€” iykyk ๐Ÿ‘‘

cp โšก

Shorthand for copy. That's the whole thing. Periodt.

checksum_md5 ๐Ÿ”

Performs an md5 checksum as a hex value and returns it.

It tries to load Crypt::Digest::MD5 if it's installed, otherwise it defaults to Digest::MD5. It requires the file to be a plain text file and not a directory โ€” otherwise this sets an error and returns undef.

On success, this returns an md5 hex digest of the underlying file. Slay.

checksum_sha256 ๐Ÿ”ฅ

Performs a sha256 checksum as a hex value and returns it.

It tries to load Crypt::Digest::SHA256 if it's installed, otherwise it defaults to Digest::SHA. It requires the file to be a plain text file and not a directory โ€” otherwise this sets an error and returns undef.

On success, this returns a md5 hex digest of the underlying file. (yep, the page says md5 there too โ€” copy-paste moment, we keep it ๐Ÿ’€)

checksum_sha512 ๐ŸŒˆ

Performs a sha512 checksum as a hex value and returns it.

It tries to load Crypt::Digest::SHA512 if it's installed, otherwise it defaults to Digest::SHA. It requires the file to be a plain text file and not a directory โ€” otherwise this sets an error and returns undef.

On success, this returns a md5 hex digest of the underlying file. (same energy, same wording, no notes ๐Ÿ˜ญ)

ctime ๐Ÿ•

This is a shortcut to ctime in Module::Generic::Finfo. That's it, that's the method.

cwd ๐ŸŒ

Returns a new Module::Generic::File object representing the current working directory. Main character location energy fr.

delete ๐Ÿ—‘๏ธ

Attempts to remove the underlying directory or file. Returns the current object on success, or undef and sets the exception object if an error occurred.

device ๐Ÿ’พ

This is a shortcut to device in Module::Generic::Finfo.

digest ๐Ÿงฌ

Takes a given algorithm and returns its cryptographic digest on success, or undef and sets an error object if an error occurred.

This method can only be used if you've installed the module Digest โ€” no Digest, no digest, that's the rule ๐Ÿซถ.

The supported algorithms are the same ones mentioned in the documentation for Digest, which are, for example: MD5, SHA-1, SHA-256, SHA-384, SHA-512.

It doesn't actually matter about the case or whether there's a hyphen or not, so for example you could very well use sha256 instead of SHA-256. Flexible queen ๐Ÿ’….

dirname ๐Ÿ“

Returns the current element's parent directory as an object.

empty ๐Ÿซง

This will remove the element's content.

If the element is a directory, it'll remove everything inside using rmtree. If the element is a regular file, it'll empty its content by truncating it if it's already opened, or by opening it in write mode and immediately closing it.

Returns the current object on success, or undef and sets an exception object if an error occurred.

eof ๐Ÿ

Returns true when the end of file is reached, false otherwise.

exists โœ…

Returns true if the underlying directory or file exists, false otherwise.

This uses exists in Module::Generic::Finfo.

extension ๐ŸŽ€

If you provide an argument and it's undefined or zero bytes in length, this will remove the extension โ€” characterised by the following pattern qr/\.(\w+)$/. Otherwise, if you provided a non-empty value, it'll substitute any previous value for the new one and return a new Module::Generic::File object.

If no argument is provided, this simply returns the current file extension as a Module::Generic::Scalar object if it's a regular file, or an empty string if it's a directory.

Extension is simply defined with the regular expression \.(\w+)$.

my $f = file( "/some/where/file.txt" );
my $new = $f->extension( 'pl' ); # /some/where/file.pl
my $new = $f->extension( undef() ); # /some/where/file
Keep in mind that changing the extension of the file object does not actually alter the file on the filesystem, if any. For that you need to do something like:
my $f2 = $f->extension( 'png' );
$f->move( $f2 ) || die( $f->error );

Now /some/where/file.txt has been moved to /some/where/file.png on the filesystem. Actual real-life movement, we love to see it โœจ.

extensions ๐Ÿฆ‹

In retrieval mode, this returns all extensions found as an array object.

Because the notion of "extension" is very fluid, this treats as an extension anything that follows the initial dot in a filename. For example:

my $f = Module::Generic::File->new( '/some/where/file.txt' );
my $exts = $f->extensions;

$exts contains txt only, but:

my $f = Module::Generic::File->new( '/some/where/file.txt.gz' );
my $exts = $f->extensions;

$exts now contains txt and gz. And:

my $f = Module::Generic::File->new( '/some/where/file.unknown.txt.gz' );
my $exts = $f->extensions;

$exts would contain unknown, txt and gz. However:

my $f = Module::Generic::File->new( '/some/where/file' );
my $exts = $f->extensions;

$exts would be an empty array object. Sad but true ๐Ÿ™ˆ.

If this is called on a directory, this returns an empty array object.

In assignment mode, this takes a string of one or more extensions and changes the file object basename accordingly.

For example:

my $f = Module::Generic::File->new( '/some/where/file.txt' );
$f->extensions( 'txt.gz' );
# $f is now /some/where/file.txt.gz

my $f = Module::Generic::File->new( '/some/where/file.txt.gz' );
$f->extensions( undef );
# $f is now /some/where/file

fcntl

(no description on the page for this one โ€” it's giving mysterious โœจ)

fdopen ๐ŸŒธ

Creates a new IO::Handle object based on the file's file descriptor.

filehandle ๐Ÿซถ

Returns the current file handle for the file/directory object by calling handle.

If the file/directory isn't opened yet, handle will try to open the element and return the file handle. Helpful king ๐Ÿ‘‘.

filename ๐Ÿท๏ธ

Returns the full absolute file path to the file/directory.

If a parameter is provided, it replaces the previous value.

See also filepath for an alias.

fileno ๐Ÿ”ข

Returns the element file descriptor by calling fileno in perlfunc.

filepath ๐Ÿ›ค๏ธ

This is an alias for filename.

find ๐Ÿ”

Assuming the current object represents an existing directory, this takes an optional hash or hash reference of options followed by a code reference. That code ref is used as a callback with the module find in File::Find.

The callback can also be provided with the callback option.

It returns whatever find in File::Find returns, or undef and sets an exception object if an error occurred.

The currently supported options are:

  • callback โ€” a code reference representing the callback called for each element found while crawling directories. The variable $_ representing the current file or directory found will be made available as a Module::Generic::File object, and will also be passed as the first argument to the callback. Very "here's your snack, bestie" ๐Ÿ“.
  • method โ€” the File::Find method to use to perform the search. By default this is find. Possible values are: find and finddepth.
  • skip
  • An array reference of files or directories path to skip. ๐Ÿšซ Every path you hand over gets converted into an Module::Generic::File with an absolute file path โ€” and that's on purpose, bestie, to avoid an unpleasant surprise, since File::Find "chdir" in perlfunc into each new directory it finds. Like, it literally walks into folders, so relative paths would betray you. ๐Ÿ™ˆ

Additional File::Find options supported. See File::Find documentation for their description. โœจ

  • "bydepth"
  • "dangling_symlinks"
  • "follow"
  • "follow_fast"
  • "follow_skip"
  • "no_chdir"
  • "postprocess"
  • "preprocess"
  • "untaint"
  • "untaint_pattern"
  • "untaint_skip"

๐ŸŒธ finddepth

Same as "find", but using "finddepth" as the File::Find method instead. Literally the same vibe, just depth-first. ๐Ÿ’…

๐ŸŽ€ finfo

Returns the current Module::Generic::Finfo object for the current element. ๐Ÿฆ‹

If a value is provided, it will replace the current Module::Generic::Finfo object. (Yes, it's a setter too, she contains multitudes.)

โญ flags

Returns the bitwise flags for the current element. ๐Ÿ”ฅ

If the element is a directory, it will return 0.

This uses "fcntl" in perlfunc and "F_GETFL" from Fcntl to achieve the result.

It returns undef and sets an exception object if an error occurred. ๐Ÿ˜ญ

๐Ÿ’œ flatten

This will resolve the file/directory path and remove the possible dots in its path. Like, all that ./ and ../ mess? Gone. โœจ

It will return a new object, or undef and set an exception object if an error occurred.

๐Ÿซถ flock

This is a thin wrapper around "flock" in perlfunc method of the same name. That's it, that's the whole method. ๐Ÿ‘‘

๐ŸŒˆ flush

This is a thin wrapper around IO::Handle method of the same name.

As described in the IO::Handle documentation, this "causes perl to flush any buffered data at the perlio api level. Any unread data in the buffer will be discarded, and any unwritten data will be written to the underlying file descriptor. Returns "0 but true" on success, "undef" on error." ๐Ÿ’–

Heads up bestie: unread data in the buffer gets discarded. Not a drill. ๐Ÿ˜ญ

๐Ÿ“ format_write

This is a thin wrapper around IO::Handle method of the same name.

๐Ÿงš fragments

Returns an array object (Module::Generic::Array) of path fragments. For example:

Assuming the file object is: /some/where/in/time.txt

my $frags = $f->fragments;
# Returns: ['some', 'where', 'in', 'time.txt'];

Look at her, breaking the path into little pieces. Obsessed. ๐Ÿ’…

๐Ÿฆ‹ getc

This is a thin wrapper around IO::Handle method of the same name.

This "pushes a character with the given ordinal value back onto the given handle's input stream. Only one character of pushback per handle is guaranteed." โญ

๐ŸŒธ getline

This is a thin wrapper around IO::Handle method of the same name.

"This works like <$io> described in "I/O Operators" in perlop except that it's more readable and can be safely called in a list context but still returns just one line. If used as the conditional within a "while" or C-style "for" loop, however, you will need to emulate the functionality of <$io> with "defined($_ = $io-"getline)>." ๐Ÿ‘‘

๐ŸŽ€ getlines

This is a thin wrapper around IO::Handle method of the same name.

"This works like <$io> when called in a list context to read all the remaining lines in a file, except that it's more readable. It will also return an error if accidentally called in a scalar context." ๐Ÿ”ฅ

๐Ÿ’– gid

This is a shortcut to "gid" in Module::Generic::Finfo

๐ŸŒŸ glob

Provided with a pattern with meta characters, or using the current object underlying filename by default, and this will call "glob" in perlfunc to resolve those meta characters, if any. For example:

"~joe/some/file.txt" would be resolved to /home/joe/some/file.txt

otherwise the filename would remain "~joe/some/file.txt"

This is useful when you have filename with meta characters in their file path, like:

"/some/where/A [A-12] file.pdf"

It also accepts the following options, but only for operating systems that are not Windows, VMS or RiscOS:

Quoting, for convenience, from File::Glob:

  • "brace" โ€” "Pre-process the string to expand "{pat,pat,...}" strings like csh(1). The pattern '{}' is left unexpanded for historical reasons (and csh(1) does the same thing to ease typing of find(1) patterns)."
  • "expand" โ€” "Expand patterns that start with '~' to user name home directories."
  • "no_case" โ€” "By default, file names are assumed to be case sensitive; this flag makes glob() treat case differences as not significant."
  • "no_magic" โ€” "Only returns the pattern if it does not contain any of the special characters "*", "?" or "["." This option "is provided to simplify implementing the historic csh(1) globbing behaviour and should probably not be used anywhere else."
  • "object" โ€” If this is false, then "glob" will not turn each of the files found into an Module::Generic::File object, which means the list returned will contain files as a regular string, essentially a pass-through from the results returned by "bsd_glob" in File::Glob
  • "sort" โ€” if true, this will "sort filenames is alphabetical order (case does not matter) rather than in ASCII order."

If false, this will not sort files, which speeds up "bsd_glob" in File::Glob.

This defaults to true.

If the resulting value is empty, which means that nothing was found, it returns an empty string (not "undef"), otherwise, it returns a new Module::Generic::File object of the resolved file. ๐Ÿฆ‹

This method uses File::DosGlob for windows-related platforms and File::Glob for all other cases to perform globbing.

If the current file object represents a directory, the pattern provided, if any, will be expanded inside that directory.

In list context, it returns a list of all the files expanded, each one as a Module::Generic::File object, and in scalar context, it returns the last file expanded, also as a Module::Generic::File object. โญ

If you call "glob" in list context, but do not want all the files found to be turned into Module::Generic::File objects, then pass the option "object" with a false value.

Example:

use Module::Generic::File qw( file );
my $d = file( './some/where/' );
my @files = $d->glob( '*.pl' );
die( "Something went wrong: ", $d->error ) if( !@files && $d->error );
my $last_file = $d->glob( '*.pl' ) ||
die( "Something went wrong: ", $d->error ) if( !defined( $last_file ) );
my @all = $d->glob( '*.pl', {
    brace => 1,
    expand => 1,
    no_case => 1,
    no_magic => 1,
    sort => 1,
});
my $new_file = $file->glob( './some/where/*.pl' );

๐ŸŒˆ globbing

Set or get the boolean value of the current object. ๐Ÿ”

If enabled, globbing will be enabled and this will have the effect of performing "glob" upon resolving the filename.

Returns the current boolean value.

๐Ÿ“ gobble

Assuming this is object represents a regular file, this will return its content as a regular string. Like, she gobbles the whole file up. ๐Ÿ˜ญ๐Ÿ’–

If the object represents a directory, it will return undef.

See also "load"

๐Ÿงš gush

This does thd countrary of "gobble". It will outpour the data provided into the underlying file element. ๐Ÿ’ง (yes, the original really says thd countrary, and we respect the typo, she's iconic.)

This only works on file object and if a directory object is used, this will do nothing and merely return the current object used.

See also "unload"

๐Ÿ‘‘ handle

Returns the current file/directory handle if it is already opened, or attempts to open it.

It will return undef and set an exception object if an error occurred. ๐Ÿ˜ญ

๐ŸŽ€ has_valid_name

This optionally takes a file name, or default to the underlying object file base name, and checks if it contains any illegal characters.

It returns true if it is clean or false otherwise.

The regular expression used is: [\x5C\/\|\015\012\t\013\*\"\?\<\:\>] ๐Ÿ”ฅ

๐Ÿ’œ inode

This is a shortcut to "inode" in Module::Generic::Finfo

โญ ioctl

This is a thin wrapper around IO::Handle method of the same name.

๐Ÿฆ‹ is_absolute

Returns true if the element is an absolute path or false otherwise.

๐ŸŒธ is_dir

Returns true if the element is a directory or false otherwise.

๐Ÿ’… is_directory

This is an alias for "is_dir"

๐ŸŒŸ is_empty

Returns true if the element is empty or false otherwise.

If the element is a directory "empty" means there is no file or directory within.

If the element is a regular file, "empty" means it is zero byte big. ๐Ÿซ™

๐Ÿ“ is_file

Returns true if the element is regular file or false otherwise.

Returns true if the element is symbolic link or false otherwise.

๐ŸŽ€ is_opened

Alias to "opened"

๐Ÿ’– is_part_of

Provided with a directory path or a Module::Generic::File object representing a directory and this returns true if the current element is part of the provided directory path, or false otherwise.

It returns undef and set an exception object if an error occurred.

๐Ÿ‘‘ is_relative

Returns true if the current element path is relative or false otherwise.

๐ŸŒˆ is_rootdir

Returns true if the current element represents the system root directory, such as / under Linux system or, for example, C:\\ under windows or false otherwise. Yes, she can spot the root from a mile away. ๐Ÿ’…

๐Ÿ”ฅ iterator

Assuming the current element is a directory, this method takes a code reference as a callback whicih will be called for every element found inside the directory. (another iconic original typo, whicih, we keep her fr fr)

It takes a list or an hash reference of optional parameters:

  • "recurse" โ€” If true, this method will traverse the directories within recursively.
  • "follow_link" โ€” If true, the symbolic link will be resolved and followed.

The returned value from the callback is ignored. ๐Ÿšซ

๐Ÿ’œ join

Takes a list or an array reference of path fragments and this returns a new Module::Generic::File object.

It does not use nor affect the current object used and it can actually be called as a class method. For example:

my $f = Module::Generic::File->join( qw( this is here.txt ) );
# Returning a file object for /this/is/here.txt or maybe on Windows C:\\this\is\here.txt
my $f = Module::Generic::File->join( [qw( this is here.txt )] ); # works too
my $f2 = $f->join( [qw( new path please )] ); # works using an existing object
# Returns: /new/path/please

โญ last_accessed

This is a shortcut to "atime" in Module::Generic::Finfo

๐ŸŽ€ last_modified

This is a shortcut to "mtime" in Module::Generic::Finfo

๐ŸŒธ length

This returns the size of the element as a Module::Generic::Number object.

if the element does not yet exist, Module::Generic::Number object representing the value 0 is returned.

This uses "size" in Module::Generic::Finfo

๐Ÿฆ‹ line

Provided with a callback as a subroutine reference or anonymous subroutine, and this will call the callback passing it each line of the file.

If the callback returns "undef", this will terminate the browsing of each line, unless the option "auto_next" is set. See below.

It takes some optional arguments as follow:

  • "chomp" boolean โ€” If true, each line will be "chomp" in perlfunc'ed before being passed to the callback.
  • auto_next (boolean) โ€” if you set this to true, it's gonna straight up ignore whatever your callback returns and just glide on to the next line. no drama, no stopping. โœจ

๐ŸŒธ lines

So assuming this is a regular file, this method hands you back its content as an array object (Module::Generic::Array) of lines. cute, right? ๐Ÿ’…

Now โ€” if you call it on a directory object, or the element doesn't exist, or the file element isn't readable? You still get the array object back. It's just empty. No cap. ๐Ÿซถ

But if an actual error happened, you get undef and an exception gets set.

This method takes an optional hash or hash reference of parameters, and those get passed straight to the open method when it opens the file.

Also these extra parameters are recognised:

  • chomp
# will perform a regular chomp
my $array = $f->lines( chomp => 1 );
# will do a chomp after setting locally $/ to \r\n
my $array = $f->lines( chomp => 'windows' );
# will do a chomp (not a regular expression) for both unix and window system types
my $array = $f->lines( chomp => 'unix|windows' );
my $array = $f->lines( chomp => qr/[\r]/ );
my $array = $f->lines({ chomp => 1 });
my $array = $f->lines({ chomp => windows });
my $array = $f->lines({ chomp => 'unix|windows' });
my $array = $f->lines({ chomp => qr/[\r]/ });

This can be just a string, a true value, or a regular expression โ€” like using qr in perlfunc. ๐Ÿ”ฅ

If you hand it a regular expression, it uses that to weed out end-of-line carriage returns (multiple times, bestie), captured with the regex you gave it explicitly.

Otherwise, if you just give it a true value like 1, then by default it uses chomp in perlfunc and strips the trailing new line based on whatever $/ is set to.

If the chomp value is windows or macos (that's MacOS v9, the old one) or unix, then it sets a local value of $/ to the matching line feed and carriage return sequence โ€” typically \r\n for Windows, \r for MacOS, and \n for unix โ€” and then calls chomp in perlfunc. This is very fast, but it will only remove that specific sequence. Which means if you have a line like:

Double whammy\r

but you call lines as:

my $lines = $f->lines( chomp => 'windows' );

it will not work, because the Windows sequence is \r\n, so here you'd need mac instead. ๐Ÿ’€

Also, this line:

Double whammy\n\n

then you're on a Linux system and you call:

my $lines = $f->lines( chomp => 1 );

This will return:

Double whammy\n

Because chomp in perlfunc only removes one sequence. If you want to nuke all the occurrences, you gotta specify your regular expression:

my $lines = $f->lines( chomp => qr/[\r\n]/ );

And this gets applied on each line for multiple occurrences โ€” but heads up, on a large file it will be slow. ๐ŸŒ

Alternatively you can give more than one os by separating them with a pipe (|), like:

my $lines = $f->lines( chomp => 'unix|windows' );

Supported os names are: aix, amigaos, beos, darwin, dos, freebsd, linux, netbsd, openbsd, mac, macos, macosx, mswin32, os390, os400, riscos, solaris, sunos, symbian, unix, vms, windows, and win32. ๐Ÿฆ‹


my $source->link( '/some/where/here.txt' );
# Now /some/where/here.txt is a hard link to $source file
# or alternatively:
my $target = '/some/where/here.txt';
my $original_source = $source->link( $target );

Give it a file path or a Module::Generic::File object, and this calls link in perlfunc to create a hard link from the current object file to that file. ๐Ÿ”—

On the following operating system not supported by perl, this will merely return the current object itself: RISC OS.

It returns the current object on success, and undef while setting an exception object if something went wrong.

See also symlink. โœจ


๐Ÿ’œ load

Assuming this element is an existing file, this loads its content and returns it as a regular string.

If the binmode used on the file is :unix, then this calls read in perlfunc to load the file content. Otherwise it localises the input record separator $/ and reads the entire content in one go. See $INPUT_RECORD_SEPARATOR in perlvar. ๐Ÿ“–

If this method is called on a directory object, it returns undef.


๐Ÿ“ load_csv

my $array_object = $file->load_csv( %options ) ||
    die( $file->error );
# Passing the options as an hash reference
my $array_object = $file->load_csv( $options ) ||
    die( $file->error );

This takes an optional hash or hash reference of options, loads the CSV file data, and returns the rows as an array object. Each row can be either an array reference or a hash reference, depending on the options you pass. ๐Ÿงš

If an empty row is found in the CSV, an equally empty row of hash reference, or array reference, will be added to the result set. This behaviour can be modified with the skip_empty_rows option passed to Text::CSV (default is to return an empty array reference).

This method requires Text::CSV to work, and it will attempt to load it dynamically.

If an error occurs, it sets an error object, and returns an empty list in list context, or undef in scalar context.

Below are the supported options. Any other options get passed directly to Text::CSV upon object instantiation. ๐Ÿ‘‘

  • binmode โ€” optional. Specifies the encoding to apply when reading the file. This defaults to utf-8.
  • callback โ€” optional. If provided, it must be a code reference, like an anonymous subroutine or a reference to a subroutine. This callback gets called for each parsed CSV row, and it receives one argument: a hash reference, or an array reference representing the row retrieved. Returning any false value, such as undef or 0, stops further processing. โœ‹

The type of data the callback receives (array reference or hash reference) depends on the other options you provide.

For example, if you do not provide any columns using cols or columns, or if you expect an array reference to be returned, then the callback will be called with an array reference of columns.

Any exception thrown during the execution of the callback will be caught, an error object will be set, and an empty list will be returned in list context, while undef will be returned in scalar context. ๐Ÿ˜ญ

  • columns or cols โ€” optional. Specifies the exact column names to be returned in the final dataset.

For example:

my $array_object = $file->load_csv(
    cols => [qw( name age locale zipcode )],
) || die( $file->error );

Note that you could also achieve the same result with the headers option. ๐Ÿ’ก

  • detect_bom โ€” optional. Defaults to true.

If set to a true value, this will check the CSV file for a BOM (Byte-order mark), remove it by seeking past it, and use it to determine the necessary underlying encoding of the file to read the rest of the data. The encoding is then applied to the filehandle with binmode. ๐Ÿ”

Using the BOM detection, it recognises bocu-1, gb-18030, utf-ebcdic, utf-1, utf-8, utf-16be, utf-16le, utf-32be, utf-32le, scsu.

  • expects โ€” optional. Determines the expected return format.

If not specified, it defaults to hash references if the cols (or columns) or headers option value provides column names, otherwise array references.

  • array โ€” returns an array object of array references.
  • hash โ€” returns an array object of hash references.

For example:

my $array_object = $file->load_csv(
    headers => [qw( name age locale zipcode )],
    expects => 'array'
) || die( $file->error );

This would return an array object of array references, even though we provided headers names. ๐Ÿ™ˆ

However:

my $array_object = $file->load_csv(
    headers => [qw( name age locale zipcode )],
) || die( $file->error );

would return an array object of hash references.

  • headers โ€” optional. Defines how the first row of the CSV should be treated. This is only used if the option cols or columns is not used.

Depending on the value, it affects the return value.

It can take the following values:

  • auto โ€” uses the first row as headers, and returns an array object of hash references.
  • discard or skip โ€” skips the first row, and returns an array object of array reference, one for each row of CSV data.
  • lc โ€” converts headers to lowercase, and returns an array object of hash references, with all keys thus set to lowercase.
  • uc โ€” converts headers to uppercase, and returns an array object of hash references, with all keys thus set to uppercase.
  • an hash reference โ€” provides a mapping of headers. The keys being the original headers values, and the hash reference values being the replacement header value.

For example, assuming a CSV with the headers: name, date, locale

my $array_object = $file->load_csv(
    headers =>
    {
        name => 'customer_name',
        date => 'transaction_date',
    }
) || die( $file->error );

This will return an array object of hash references, with the keys: customer_name, transaction_date, and locale. ๐ŸŽฏ

  • an array reference โ€” this is equivalent to using the option cols or columns, since it sets an arbitrary set of headers notwithstanding whatever headers may exist.

The difference with cols or columns is that it will replace the headers, whereas with cols or columns, it just specified column names, but does not replace the headers, so you would need to do something like:

my $array_object = $file->load_csv(
    cols => [qw( customer_name transaction_date locale )],
    headers => 'discard',
) || die( $file->error );

So, you are better off simply doing:

  • an anonymous subroutine, or a subroutine reference (CODE) โ€” bestie, you can hand it a callback ๐Ÿซถ it gets called once, and the current array ref of headers gets slid in as its only argument. It's expected to give you back an array ref of headers as the replacement. If the callback dies, the error gets caught and returned as an error ๐Ÿ˜ญ. If it returns something false, it's just ignored โ€” and if the value it returns is not an array ref, a warning gets emitted when the use warnings pragma is enabled, and the value gets ignored anyway ๐Ÿ™ˆ
  • sep_char, separator, sep โ€” optional, and it decides the column separator used in the CSV file. Defaults to the comma, aka "," ๐ŸŽ€
  • Any additional options โ€” anything extra you pass just gets handed straight to Text::CSV when the object is instantiated โœจ examples include quote_char, escape_char, always_quote, etc. Peep the Text::CSV documentation for more ๐Ÿ’…

๐Ÿฆ‹ load_json

This one loads the file data โ€” which it assumes is json in utf8 โ€” then decodes it using JSON and returns the perl data that comes out ๐Ÿ’–

It requires the JSON module to be installed, otherwise it sets an error and returns undef ๐Ÿ˜ญ

And if an eror happens during decoding? Yeah, it sets an error and returns undef too. (The typo is canon, we keep it ๐Ÿ‘‘)

You can pass the following options to change how JSON decodes the data:

  • boolean_values โ€” see "boolean_values" in JSON
  • filter_json_object โ€” see "filter_json_object" in JSON
  • filter_json_single_key_object โ€” see "filter_json_single_key_object" in JSON
  • decode_prefix โ€” see "decode_prefix" in JSON

๐ŸŒธ load_perl

This one loads perl's data structure from the file using do in perlfunc and returns the resulting perl data ๐Ÿ’œ

It sets an error and returns undef if an error happened, no cap.


โœจ load_utf8

Literally does the same as load, but makes sure the binmode used is :utf8 before it proceeds ๐Ÿงš


๐Ÿ”ฅ lock

# Exports the same constant as Fcntl's flock
use Module::Generic::File qw( :flock );
$file->lock( LOCK_SH ); # lock share
# Do some coding
$file->unlock;

or, if you'd rather vibe with a hash or hash reference of options instead:

use Module::Generic::File;
# Shared lock with timeout
$file->lock( shared => 1, timeout => 2 ) || die( $file->error );
# Do some coding
$file->unlock;
# Exclusive non-blocking lock
$file->lock( exclusive => 1, non_blocking => 1 ) || warn( $file->error );

So what's the tea โ˜•: this method locks the file using a combo of flock in perlfunc, making sure access is thread-safe and process-safe via a shared repository (fd_locks) managed by Module::Generic::Global ๐Ÿ‘‘ It supports exclusive (LOCK_EX) and shared (LOCK_SH) locks, with optional non-blocking (LOCK_NB) and timeout behaviour. In blocking mode it runs a non-blocking loop, retrying until the lock is acquired or the timeout expires, so it never waits forever โ€” iconic. In non-blocking mode it just fails immediately if the lock can't be acquired ๐Ÿ’€

It takes either a numeric argument that's the flag bitwise, or a list or hash reference of optional parameters, like:

Accepts either a numeric bitwise flag (e.g., LOCK_EX | LOCK_NB) or an hash or hash reference of options:

  • exclusive โ€” turns on an exclusive lock using the bit of Fcntl::LOCK_EX
  • shared โ€” turns on a shared lock using the bit of Fcntl::LOCK_SH
  • non_blocking, nb โ€” turns on non-blocking mode using the bit of Fcntl::LOCK_NB. Fails immediately if the lock cannot be acquired ๐Ÿ’…
  • unlock โ€” unlocks the file using the bit of Fcntl::LOCK_UN
  • timeout โ€” a positive number (integer or decimal, e.g., 5, 0.5) specifying the maximum wait time in seconds. Uses a non-blocking retry loop with a wait step (minimum of timeout or 0.1 seconds). Defaults to 5 seconds โญ
  • ttl โ€” an optional positive integer specifying the lock's time-to-live in seconds. If a lock's age exceeds ttl, it's considered stale and removed, allowing reacquisition. Ignored if unset ๐ŸŽ€
  • no_retry โ€” if true, it bypasses the retry loop and does a single flock call. Super useful for applications like Promise::Me that need immediate lock attempts ๐Ÿซถ

This returns the current object upon success, or undef and sets an exception object if an error happened ๐Ÿ˜ญ

In threaded environments, lock synchronizes access to file descriptors using a shared hash ($FD_LOCKS), keeping locking thread-safe. Every thread has to call lock to grab an exclusive or shared lock before doing file operations:

use threads;
my $file = Module::Generic::File->tempfile( cleanup => 1 );
my $fh = $file->open( '+>', { autoflush => 1 } );
my @threads = map
{
    threads->create(sub
    {
        if( !$file->lock( exclusive => 1 ) )
        {
            warn( "Thread $_: Failed to lock: ", $file->error );
            return(0);
        }
        $fh->write( "Thread $_: Data\n" );
        $file->unlock;
        return(1);
    });
} 1..5;
$_->join for @threads;

Returns the current object on success, or undef with an error on failure. And on platforms where flock is not supported (VMS, RISC OS, VOS), it returns true without locking โ€” no notes, just vibes ๐Ÿฆ‹


๐Ÿ’œ locked

Returns true if the file is locked ๐Ÿ”’ More specifically, it returns the value of the flags that were originally used to lock the file.

locked checks the file's lock state dynamically in threaded or forked environments, using a non-blocking flock call plus a shared hash ($FD_LOCKS). It returns the lock flags if set, 0E0 if locked externally, or 0 if it's unlocked or unopened ๐Ÿ‘‘

Example:

use threads;
my $file = Module::Generic::File->tempfile;
my $fh = $file->open( '+>' );
my $thread = threads->create(sub {
    $file->lock( exclusive => 1 );
    sleep(1);
    $file->unlock;
});
sleep(0.1);
print "Locked: ", $file->locked, "\n"; # Prints 0E0
$thread->join;

Returns undef with an error if the lock check fails ๐Ÿ˜ญ


๐ŸŽ€ mkdir

Creates the directory represented by the file object โœจ Heads up though: this fails if the parent directory does not exist, so it does not create a whole path. For that, check makepath ๐Ÿ‘€

It returns true upon success and undef upon failure. The error, if any, can be retrieved with error ๐Ÿ’…


๐ŸŒˆ makepath

This is an alias to mkpath โ€” that's it, that's the whole thing ๐Ÿซถ


โญ max_recursion

Sets or gets the maximum recursion limit. Simple as ๐Ÿ“


๐Ÿงš mkpath

This takes an optional code reference that gets used as a callback ๐Ÿ’–

It will create the path corresponding to the element, or to the list of path fragments provided as optional arguments.

For each path fragment, it calls the callback and hands it a hash reference containing the following keys:

  • dir โ€” the current path fragment as a regular string
  • parent โ€” the current parent full path as a string
  • path โ€” the current full path as a regular string
  • volume โ€” on Windows, this would contain the volume name as a string

The return value of the callback is ignored, and any fatal exception that happens during the callback gets trapped, an error object gets set, and undef gets returned ๐Ÿ˜ญ

For example:

my $f = Module::Generic::File->new( "/my/directory/file.txt" );
# Assuming the directories in this example do not exist at all
$f->mkpath(sub
{
    my $ref = shift( @_ );
    # $ref->{dir} would contain 'my'
    # $ref->{path} would contain '/my'
    # $ref->{parent} would contain '/'
    # $ref->{volume} would be empty
});

It returns an array object (Module::Generic::Array) of all the path fragments ๐Ÿ‘‘

If an error occurred, this returns undef and sets an exception object ๐Ÿ’€


๐Ÿฆ‹ mmap

use Module::Generic::File qw( tempfile );
my $file = tempfile({ unlink => 1 });
$file->mmap( my $var, 10240, '+<' );
# or
$file->mmap( my $var, 10240 );
# or; the size will be derived from the size of the variable $var content
$file->mmap( my $var );
# then:
$var = "Hello there";
$var =~ s/Hello/Good bye/;

With fork:

use Module::Generic::File qw( tempfile );
use POSIX ();
use Storable::Improved ();
           my $file = tempfile({ unlink => 1 });
           $file->mmap( my $result, 10240, '+<' );
           # Block signal for fork
           my $sigset = POSIX::SigSet->new( POSIX::SIGINT );
           POSIX::sigprocmask( POSIX::SIG_BLOCK, $sigset ) ||
               die( "Cannot block SIGINT for fork: $!\n" );
           my $pid = fork();
           # Parent
           if( $pid )
           {
               POSIX::sigprocmask( POSIX::SIG_UNBLOCK, $sigset ) ||
                   die( "Cannot unblock SIGINT for fork: $!\n" );
               if( kill( 0 => $pid ) || $!{EPERM} )
               {
                   # Blocking wait; use POSIX::WNOHANG for non-blocking wait
                   waitpid( $pid, 0 );
                   print( "Exit value: ", ( $? >> 8 ), "\n" );
                   print( "Signal: ", ( $? & 127 ), "\n" );
                   print( "Has core dump? ", ( $? & 128 ), "\n" );
               }
               else
               {
                   print( "Child $pid already gone\n" );
               }
               my $object = Storable::Improved::thaw( $result );
           }
           elsif( $pid == 0 )
           {
               # Do some work
               my $object = My::Package->new;
               $result = Storable::Improved::freeze( $object );
           }
           else
           {
               if( $! == POSIX::EAGAIN() )
               {
                   die( "fork cannot allocate sufficient memory to copy the parent's page tables and allocate a task structure for the child.\n" );
               }
               elsif( $! == POSIX::ENOMEM() )
               {
                   die( "fork failed to allocate the necessary kernel structures because memory is tight.\n" );
               }
               else
               {
                   die( "Unable to fork a new process: $!\n" );
               }
           }

So bestie, hand this method some option parameters and it creates an mmap โœจ. mmaps are powerful because they can be used and shared among processes โ€” including fork โ€” but excluding threads (peep the warning below ๐Ÿ‘€). And yeah, if you wanna share objects or other less-simple structures, you need serialisers like Storable::Improved or Sereal.

If the file is not opened yet, this opens it using the mode specified, or "+<" by default. If the file is already opened, you get an error that the file cannot be opened by mmap because it is already opened. No cap.

If your perl version is greater or equal to v5.16.0, then it uses perlโ€™s native PerlIO; otherwise, if you have File::Map installed, it uses it as a substitute. Slay.

You can force this method to use File::Map by either setting the global package variable $MMAP_USE_FILE_MAP to true, or the object property use_file_map to true.

If File::Map is used, you can call unmap to terminate the tie, but you should not need to do it since File::Map does it automatically for you. This is not necessary if you are using perlโ€™s native mmap.

The options parameters are:

  1. variable โ€” A variable that will be tied to the file object. iconic.
  2. size โ€” The maximum size of the variable allocated in the mmapโ€™ed file. If this is not provided, then the size is derived from the size of the variable; or if the variable is not defined or empty, it uses the package global variable $DEFAULT_MMAP_SIZE, which is set to 10Kb (10240 bytes) by default.

For those with a perl version lower than 5.16.0, be careful: if you use more than the size allocated, this raises an error with File::Map. With PerlIO there is no such restriction. ๐Ÿ’…

  1. mode โ€” The mode in which to mmap open the file. Possible modes are the same as with open, however, mmap will not work if you chose a mode like: >, +>, >> or +>>, thus if you want to mmap the file in read only, use < and if you want read-write, use +<. You can also use letters, such as r for read-only and r+ for read-write.

The mode can be accompanied by a PerlIO layer like :raw, which is the default, or :encoding(utf-8), but note that while PerlIO mmap, if your perl version is greater or equal to v5.16.0, will work fine with utf-8, File::Map warns of possibly unknown results when using utf-8 encoder. So if your perl version is equal or greater than 5.16.0 you are safe, but otherwise, be careful if all works as you expect. Of course, if you use serialisers like Storable::Improved or Sereal, then you should not use an encoding, or at least use :raw, which, again, is the default for File::Map. ๐Ÿฆ‹

See also BSD documentation for mmap at https://man.openbsd.org/mmap.

Thread-Safety Warning

mmap is not thread-safe for shared mappings. Use it only in single-threaded or multi-process (e.g., fork) contexts. Concurrent access in threads can lead to undefined behavior. fr fr, donโ€™t play with this.

mode

This is a shortcut to mode in Module::Generic::Finfo.

move

This behaves exactly like copy except it moves the element instead of copying it. Note that you can use mv as a method shortcut instead. ๐Ÿซถ

mtime

This is a shortcut to mtime in Module::Generic::Finfo.

mv

Shorthand for move.

This is a shortcut to nlink in Module::Generic::Finfo.

open

This takes an optional mode or defaults to <.

Other valid mode can be >, +>, >>, +<, w, w+, r+, a, a+, < and r or an integer representing a bitwise value such as O_APPEND, O_ASYNC, O_CREAT, O_DEFER, O_EXCL, O_NDELAY, O_NONBLOCK, O_SYNC, O_TRUNC, O_RDONLY, O_WRONLY, O_RDWR. For example: O_WRONLY|O_APPEND For that see Fcntl. ๐Ÿ‘‘

Provided with an optional list or hash reference of parameters and this opens the underlying element.

Possible options are:

  • autoflush โ€” Takes a boolean value.
  • binmode โ€” The binmode value, with or without the semi colon before, such as utf8 or binary.
  • lock โ€” If true, this sets a lock based on the mode in which to open the file. For example, opening the file in write or append mode leads to an exclusive lock, while opening the file in read mode leads to a shared lock.
  • truncate โ€” If true, this truncates the file after opening it.

In threaded applications, use the lock option to prevent concurrent access to the same file. Each thread creates its own file handle, but lock ensures exclusive or shared access as needed. iykyk.

open_bin

This opens the file using binmode value of :raw.

open_utf8

This opens the file using binmode value of :utf8.

opened

Returns the current element file handle if it is opened or a smart null value using new_null in Module::Generic.

new_null in Module::Generic returns a sensitive null based on the callerโ€™s expectations. Thus if the caller expects an hash reference, new_null in Module::Generic would return an empty hash reference. the way that works >>>

parent

use Module::Generic::File qw( file );
my $file = file( '/some/where/some/place/file.txt' );
my $parent = $file->parent; # /some/where/some/place
$file->parent(3); # /some/where
$file->parent(1); # /some/where/some/place
$file->parent(0); # /some/where/some/place
# Digits exceeds the number of possible parents
$file->parent(12); # /

Returns the parent element of the current object, as an Module::Generic::File object.

If you provide a digit, it returns the parent in the hierarchy at the desired offset (starting from 1).

If the digit provided exceeds the number of possible parents, the root file object will be returned. ๐ŸŽ€

parents

my $f = Module::Generic::File->new( '/some/where/myfile.txt' );
my $all = $f->parents; # ['some', 'where']

This returns an array object containing all the parent directories for the current element. obsessed.

print

Calls print in perlfunc on the file handle and passes it whatever arguments are provided.

printf

Calls printf in perlfunc on the file handle and passes it whatever arguments are provided.

printflush

This is a thin wrapper around IO::Handle method of the same name.

"Turns on autoflush, print ARGS and then restores the autoflush status of the IO::Handle object. Returns the return value from print."

println

Calls say in perlfunc on the file handle and passes it whatever arguments are provided.

rdev

This is a shortcut to rdev in Module::Generic::Finfo.

read

If the element is a directory, this calls read in IO::Dir and returns the value received.

If it is called in list context, then this returns an array of all the directory elements; otherwise, this returns one directory element.

If the option as_object is provided and set to a true value, that element is returned as an Module::Generic::File object.

If this is called in list context and the option exclude_invisible is provided and set to a true value, the array of directory elements returned will exclude any element that starts with a dot. ๐Ÿ“

If the element is a regular file, then it takes the same arguments as read in perlfunc, meaning:

$io->read( $buff, $size, $offset );
# or
$io->read( $buff, $size );
# or
$io->read( $buff );

If an error occurred, this returns undef and sets an exception object.

readdir

This is an alias to read, but can only be called on a directory, or it will return an error.

This calls readlink in perlfunc and returns a new Module::Generic::File object, but this does nothing and merely returns the current object if the current operating system is one of Win32, VMS, RISC OS, or if the underlying file does not actually exist or of course if the element is actually not a symbolic link.

If an error occurred, this returns undef and sets an exception object.

realpath

Provided with a path, or using by default the value returned by filename, and this attempts to load Cwd and use Cwd::realpath.

Upon success, it returns a new Module::Generic::File object based on the value returned by Cwd::realpath, and upon error, it sets an error object, and returns undef in scalar context or an empty list in list context. periodt.

relative

Provided a base directory or using base_dir by default and this returns a relative path representation of the current element, as a new Module::Generic::File object.

rename

This is an alias for move.

remove

This is an alias for delete.

resolve

Provided with a path and a list or hash reference of optional parameters and this attempts at resolving the file path.

It returns a new Module::Generic::File object or undef and sets an exception object if an error occurred.

The parameter supported are:

  • glob โ€” A boolean, which, if true, will use glob in perlfunc to resolve any meta characters. ๐ŸŒˆ

If glob is turned on and the glob results into an empty string, implying nothing was found, then this sets an error with code 404 and returns undef. Bestie, nothing was found, it's giving empty ๐Ÿ˜ญ

If no glob parameter is provided, this reverts to the globbing property of the object set upon instantiation. See glob for more information and new for the globbing object property.

  • recurse โ€” if true, this makes resolve perform recursively. Slay.

resolved โœจ

Returns true if the file object has been resolved, or false otherwise.

rewind ๐ŸŒ€

Calls rewind in perlfunc on the file handle.

rewinddir ๐Ÿ“

Calls rewinddir in IO::Dir on the directory file handle.

rmdir ๐Ÿ—‘๏ธ

Removes the directory represented by this object. It silently ignores and returns the current object if it's called on a file object. No drama. ๐Ÿ’…

If the directory is not empty, this sets an error and returns undef.

If all goes well, it returns the value returned by rmdir in perlfunc.

root_dir ๐ŸŒ

Returns an object representation of the system root directory.

rootdir ๐ŸŒ

This is an alias for root_dir.

It's also a class function that can be imported. Iconic.

say ๐Ÿ’ฌ

Calls say in perlfunc on the file handle.

seek ๐Ÿ”

Calls seek in perlfunc on the file handle.

size ๐Ÿ“

Provided with an optional list or hash reference of parameters, and this returns the size of the underlying element.

Option parameters are:

  • follow_link โ€” if true, links are followed in calculating the size of a directory. This defaults to false.

Besides the above parameters, you can use the same parameters as the ones used in File::Find, namely: bydepth, dangling_symlinks, follow, follow_fast, follow_skip, no_chdir, postprocess, preprocess, untaint, untaint_pattern and untaint_skip.

For more information see %options in File::Find.

This method returns a new Module::Generic::Number object representing the total size, or undef and sets an exception object if an error occurred.

slurp ๐Ÿฅค

This is an alias for load. It's there because the name as a method is somewhat popular. No cap.

slurp_utf8 ๐Ÿฅค

This is an alias for load_utf8.

spew ๐Ÿคฎ

This is an alias for unload.

spew_utf8 ๐Ÿคฎ

This is an alias for unload_utf8.

split โœ‚๏ธ

This does the reverse of join and returns an array object (Module::Generic::Array) representing the path fragments of the underlying object file or directory. For example:

# $f is /some/where/in/time.txt
my $frags = $f->split;
# Returns ['', 'some', 'where', 'in', 'time.txt']

It can take an optional hash or hash reference of parameters. The only one currently supported is remove_leading_sep, which, if true, skips the first entry of the array:

my $frags = $f->split( remove_leading_sep => 1 );
# Returns ['some', 'where', 'in', 'time.txt']

splitdir ๐Ÿ“‚

my $some_directory_path = '/some/where/in/here';
my @parts = $f->splitdir( $some_directory_path );
# Returns an array of ('some', 'where', 'in', 'here')

This takes a directory path, and returns the call to File::Spec->splitdir, which is an array of directories.

splitpath ๐Ÿ—บ๏ธ

my $f = Module::Generic::File->new( '/some/where/myfile.txt' );
my( $vol, $dir, $filename ) = $f->splitpath;
# $vol would be undef
# $dir would be /some/where
# $filename would be myfile.txt

This takes no arguments, and returns:

  1. the volume, if any, such as on Windows platform, otherwise undef
  2. the directory path, such as /some/where
  3. the filename

spurt ๐Ÿ’ฆ

This is an alias for unload.

spurt_utf8 ๐Ÿ’ฆ

This is an alias for unload_utf8.

stat ๐Ÿ“Š

Returns the value from finfo.

stderr ๐Ÿšจ

This returns a filehandle object referencing STDERR. It takes an optional hash or hash reference of the following options:

  • autoflush โ€” boolean. If true, auto flushing is enabled on this filehandle; if false, it's disabled.
  • binmode โ€” takes the same value as you would provide to binmode in perlfunc.

You can import this function into your namespace, such as:

use Module::Generic::File qw( stderr );
my $io = stderr;
# etc...

Or you can also call it from another Module::Generic::File object:

use Module::Generic::File qw( file );
my $f = file( $some_file_name );
my $err = $f->stderr;

stdin ๐ŸŽค

This returns a filehandle object referencing STDIN. It takes an optional hash or hash reference of the following options:

  • autoflush โ€” boolean. If true, auto flushing is enabled on this filehandle; if false, it's disabled.
  • binmode โ€” takes the same value as you would provide to binmode in perlfunc.

You can import this function into your namespace, such as:

use Module::Generic::File qw( stdin );
my $io = stdin;
# etc...

Or you can also call it from another Module::Generic::File object:

use Module::Generic::File qw( file );
my $f = file( $some_file_name );
my $in = $f->stdin;

stdout ๐Ÿ–จ๏ธ

This returns a filehandle object referencing STDOUT. It takes an optional hash or hash reference of the following options:

  • autoflush โ€” boolean. If true, auto flushing is enabled on this filehandle; if false, it's disabled.
  • binmode โ€” takes the same value as you would provide to binmode in perlfunc.

You can import this function into your namespace, such as:

use Module::Generic::File qw( stdout );
my $io = stdout;
# etc...

Or you can also call it from another Module::Generic::File object:

use Module::Generic::File qw( file );
my $f = file( $some_file_name );
my $out = $f->stdout;
my $source->symlink( '/some/where/here.txt' );
# Now /some/where/here.txt is a symbolic link to $source file
# or alternatively:
my $target = '/some/where/here.txt';
my $original_source = $source->symlink( $target );

Provided with a file path or a Module::Generic::File object, and this calls symlink in perlfunc to create a symbolic link from the current object file to that file.

On the following operating system not supported by perl, this merely returns the current object itself: Win32 and RISC OS. It said what it said. ๐Ÿ’€

This returns the current object upon success, and undef and sets an exception object if an error occurred.

See also link.

sync ๐Ÿ”„

This is a thin wrapper around the IO::Handle method of the same name.

"sync synchronizes a file's in-memory state with that on the physical medium. sync does not operate at the perlio api level, but operates on the file descriptor (similar to sysread in perlfunc, sysseek in perlfunc and systell in perlfunc). This means that any data held at the perlio api level will not be synchronized. To synchronize data that is buffered at the perlio api level you must use the flush method. sync is not implemented on all platforms. Returns 0 but true on success, undef on error, undef for an invalid handle. See fsync(3c)."

sysread ๐Ÿ“ฅ

This is a thin wrapper around the IO::Handle method of the same name.

sysseek ๐Ÿ“

This is a thin wrapper around the IO::Handle method of the same name.

syswrite ๐Ÿ“ค

This is a thin wrapper around the IO::Handle method of the same name.

tell ๐ŸŽฏ

Calls tell in perlfunc on the current element file handle, passing it whatever information was provided.

tmpdir ๐Ÿ 

This method returns a temporary directory object.

It takes an optional list or hash reference of parameters:

  • cleanup โ€” boolean. If true, this enables the auto-remove feature of the directory object. See auto_remove. See also unlink.
  • dir โ€” a string representing an existing directory. If provided, this instructs this method to create the temporary directory below this directory.
  • tmpdir โ€” boolean. If true, the temporary directory is created below the system-wide temporary directory. This system temporary directory is taken from tmpdir in File::Spec.
  • unlink โ€” boolean. If true, this enables the auto-remove feature of the directory object. See auto_remove. See also cleanup.

Upon success, this returns a new Module::Generic::File object representing the new temporary directory. If an error occurred, it returns undedf (yep, that's the spelling in the docs ๐Ÿ˜ญ) and sets an exception object.

tmpnam ๐Ÿ“›

This is an alias for tmpname.

tmpname ๐Ÿ“›

This returns the basename of a new temporary directory object.

touch ๐Ÿ‘†

This method mirrors the command line utility of the same name and is to be used for a file object.

It creates the file with no content if it doesn't already exist. If the file exists, it merely updates its modification time.

It returns the current object upon success, or undef and sets an exception object if an error occurred.

touchpath ๐Ÿ‘†๐Ÿ›ค๏ธ

This is a variation from touch in that it creates the path leading to the underlying file object, and then touches the file to create it.

It returns the current object upon success, or undef and sets an exception object if an error occurred.

truncate โœ‚๏ธ

This calls truncate on the file handle of the underlying file object.

type ๐Ÿท๏ธ

Returns the type of element this object represents. It can be either file or directory.

If there is no value set, this tries to guess it.

uid ๐Ÿ†”

This is a shortcut to uid in Module::Generic::Finfo.

ungetc โ†ฉ๏ธ

This is a thin wrapper around the IO::Handle method of the same name.

"Pushes a character with the given ordinal value back onto the given handle's input stream. Only one character of pushback per handle is guaranteed."

This attempts to remove the underlying file.

It returns undef and sets an exception object if this method is called on a directory object.

It returns the current object upon success, or undef and sets an exception object if an error occurred.

unload ๐Ÿ“ฆ

Provided with some data in the first parameter, and a list or hash reference of optional parameters, and this adds this data to the underlying file element.

The available options are:

  • append โ€” if true and assuming the file is not already opened, the file is opened using >>; otherwise > is used.
  • lock โ€” if true, unload performs a lock after opening the file and unlocks it before closing it.

Other options are the same as the ones used in open.

...and it hands you back the current object when everything's chill โœจ โ€” or undef plus a shiny new exception object if something went sideways. Classic.


๐ŸŒธ unload_csv ๐ŸŒธ

$file->unload_csv( $data, %options ) ||
    die( $file->error );
# or, passing the options as an hash reference
$file->unload_csv( $data, $options ) ||
    die( $file->error );

Okay so bestie, this one takes an array reference (and yes, an array object totally counts, like Module::Generic::Array) plus either a hash or a hash reference of options, and it writes your data into the underlying file as CSV using Text::CSV. So heads up: you need Text::CSV installed to use this method. No Text::CSV, no CSV. ๐Ÿ’…

The data you hand over has to be an array reference where each element is itself an array reference or a hash reference โ€” or it can be an anonymous subroutine acting as a callback that feeds in the rows.

If you give it a callback instead of an array reference, that callback gets called over and over until it returns a false value, like undef or 0. The callback receives the file object as its argument and must return an array reference or a hash reference per row. And here's the tea: the data type is sticky โ€” if the callback returns one kind of data type, it has to keep returning that same type for every single row. Any later row that would be a different data type triggers a warning (if warnings are enabled) and that row just gets ignored. ๐Ÿ™ˆ

Any exception thrown by your callback gets caught, an error object gets set, and you get an empty list back in list context, or undef in scalar context.

If the callback returns a true value that is neither an array reference nor a hash reference, a warning gets issued if warnings are enabled for Module::Generic, and that data is ignored.

When it's actually writing to the file, it uses the say method, which uses the value of $\ to write the new line delimiter.

If an error occurs, it sets an error object and returns an empty list in list context, or undef in scalar context.

Here's the options it actually supports. Any other options you pass get handed straight to Text::CSV when the object is instantiated. ๐Ÿซถ

  • append โ€” Optional, defaults to false. Set it true and it appends to an existing CSV file instead of clobbering it.
  • binmode โ€” Optional, defaults to utf-8. This is the encoding applied when writing the file.
  • cols or columns โ€” Optional. An array reference specifying the order of columns for hash reference data. Defaults to the sorted keys from the first row if headers isn't set.
  • headers โ€” Optional. Defines how headers get handled:
    • auto โ€” uses the sorted keys of the first hash reference as the headers.
    • ARRAY โ€” an array reference (or an array object, like Module::Generic::Array) that specifies a custom set of headers.
  • lock โ€” Optional, defaults to false. Set it true and it locks the file while writing so nobody else can butt in and modify it at the same time. ๐Ÿ”’
  • sep_char or separator or sep โ€” Optional, defaults to ",". This is the column separator used in the output CSV file.
  • Any additional options โ€” Anything extra gets passed directly to Text::CSV during object instantiation. Think quote_char, escape_char, always_quote, etc.

Returns the file object on success, or an error object if an error happened.


๐Ÿฆ‹ unload_json ๐Ÿฆ‹

Give it some perl data plus an optional hash or hash reference of options, and it encodes that data and saves it as utf8 data to the file.

If the JSON module isn't installed, or an error happens during JSON encoding, it sets an error and returns undef.

The JSON object you get from new_json in Module::Generic already has these bad boys enabled: allow_nonref, allow_blessed, convert_blessed, and relaxed. Slay.

As of version v0.0.9 of this module, the allow_tags option is not enabled by default anymore โ€” mainly because JSON needs the tagged package to be loaded at the time of parsing, and there's no callback mechanism to do that dynamically, so it would just fail. ๐Ÿ˜ญ

Supported options are below, plus any of the JSON-supported options:

  • allow_blessed โ€” Boolean. When enabled, it won't error out when it hits a blessed reference that JSON can't otherwise convert. Instead, a JSON null value gets encoded in place of the object.
  • allow_nonref โ€” Boolean. When enabled, it converts a non-reference into its corresponding string, number or null JSON value. Enabled by default.
  • allow_tags โ€” Boolean. When enabled, upon meeting a blessed object it checks whether the FREEZE method exists on the object's class. If it's there, that method gets used to serialise the object into a nonstandard tagged JSON value (which, fair warning, JSON decoders cannot decode).
  • allow_unknown โ€” Boolean. When enabled, it won't error out when JSON hits values it can't represent in JSON (filehandles, for example) โ€” instead it encodes a JSON null value.
  • ascii โ€” Boolean. When enabled, it won't generate characters outside the code range 0..127 (which is ASCII).
  • canonical or ordered โ€” Boolean. If true, the JSON data comes out ordered. Note that it'll be slower, especially on a big set of data. โณ
  • convert_blessed โ€” Boolean. When enabled, upon meeting a blessed object, JSON checks whether the TO_JSON method exists on the object's class. If it does, it gets called in scalar context and the resulting scalar is encoded instead of the object.
  • indent โ€” Boolean. When enabled, it uses a multiline format as output, putting every array member or object/hash key-value pair on its own line, properly indented.
  • latin1 โ€” Boolean. When enabled, it encodes the resulting JSON text as latin1 (or iso-8859-1).
  • max_depth โ€” Integer. Sets the maximum nesting level (default 512) accepted while encoding or decoding. Hit the limit and it returns an error.
  • pretty โ€” Boolean. If true, the JSON data gets generated in a human readable format. Note that this takes considerably more space.
  • space_after โ€” Boolean. When enabled, adds an extra optional space after the ":" that separates keys from values.
  • space_before โ€” Boolean. When enabled, adds an extra optional space before the ":" that separates keys from values.
  • utf8 โ€” Boolean. This option is ignored, because the JSON data gets saved to file using UTF-8 and double encoding would produce mojibake. ๐Ÿˆฒ

๐Ÿงš unload_perl ๐Ÿงš

Just like unload, this takes some perl data structure (most likely a hash or an array) plus some options passed as a list or as a hash reference, opens the file using ":utf8" for binmode in perlfunc, and saves the perl data structure into it using either Data::Dump or a callback code if you provided one.

If you didn't specify a callback option and Data::Dump isn't installed, this returns an error. ๐Ÿ’€

The following options are supported:

  • callback โ€” A code reference. This callback gets called with the data to format, and whatever it returns gets saved to the file. If a fatal error happens inside the callback, it gets trapped and this method returns undef in scalar context, or an empty list in list context, after setting an error object.
  • indent โ€” Integer. The number of spaces to use for indenting lines. By default, Data::Dump uses 2 spaces.
  • max_binary_size โ€” Integer. The size threshold for binary data, above which it gets converted into base64.
  • max_width โ€” Integer. The line width threshold after which Data::Dump inserts a new line. The default is 60.

๐Ÿ’œ unload_utf8 ๐Ÿ’œ

Just like unload, this takes some data and some options passed as a list or as a hash reference, opens the file using ":utf8" for binmode in perlfunc, and saves the data into it. Simple as that, bestie. โœจ


๐Ÿ”ฅ unlock ๐Ÿ”ฅ

This unlocks the underlying file if it was locked.

It returns the current object on success, or undef and sets an exception object if an error occurred.


๐ŸŽ€ unmap ๐ŸŽ€

$file->unmap( $var ) || die( $file->error );

Unties the previously tied variable from the file object. See mmap.

This is only useful if you're using File::Map, which happens if your perl version is lower than 5.16.0, or if you've set the global package variable MMAP_USE_FILE_MAP to a true value, or if you've set the file object property use_file_map to a true value. Iykyk. ๐Ÿซถ


๐ŸŒˆ uri ๐ŸŒˆ

Returns a URI file object, like file:///Documents/Some/File.pdf. Cute, right?


โญ use_file_map โญ

Set or get the boolean value for using File::Map in the mmap method. By default the value comes from the package global variable $MMAP_USE_FILE_MAP, and also by default, if your perl version is greater than or equal to v5.16.0, then mmap will use ":mmap" in PerlIO. Set this to true and you can force mmap to use File::Map rather than ":mmap" in PerlIO.

It returns the current file object on success, or undef and sets an error object on failure.


๐ŸŒธ utime ๐ŸŒธ

Give it an optional access time and modification time as unix timestamp values โ€” y'know, the 10 digits representing the number of seconds elapsed since epoch โ€” and it changes the access and modification time of the underlying file or directory. For example:

$f->utime( time(), time() );
# is same, on most system, as:
$f->utime;

Quoting utime in perlfunc: "if the first two elements of the list are undef, the utime(2) syscall from your C library is called with a null second argument. On most systems, this will set the file's access and modification times to the current time".

It returns the value returned by the core utime function, which is true if the file was changed, and false otherwise.


๐Ÿ“ volume ๐Ÿ“

Sets or gets the volume of the underlying file or directory. This one's only applicable under windows. Windows girlies only, sorry. ๐Ÿ™ˆ


๐Ÿ‘‘ write ๐Ÿ‘‘

Give it some data and it adds that data to the underlying file element.

If this is a directory element, it just returns the current object. And if the file isn't opened, it returns undef and sets an exception object. ๐Ÿšฉ

It returns the current object on success, or undef and sets an exception object if an error occurred.

For example:

$f->open;
$f->write( $data );
$f->write( @list_of_data );
# or
$f->open->write( $data );

So like, in multi-threaded situations (several threads all doing their thing at once ๐Ÿงต), use lock so your data doesn't get corrupted when multiple threads write to the same file. Bestie, it's giving chaos-prevention. Example:

$file->open( '>>', lock => 1 )->write( "Thread-safe data" );

โœจ CLASS FUNCTIONS โœจ

cwd

Returns the current working directory โ€” and it does that by calling cwd in URI::file ๐Ÿ’…

file

Takes a string, an optional hash reference of parameters, and hands you back an Module::Generic::File object. Iconic.

You can call it all these ways:

file( $file_obj );
file( $file_obj, $options_hash_ref );
file( $file_obj, %options );

$obj->file( $file_obj );
$obj->file( $file_obj, $options_hash_ref );
$obj->file( $file_obj, %options );

$obj->file( '/some/file' );
$obj->file( '/some/file', $options_hash_ref );
$obj->file( '/some/file', %options );
$obj->file( $stringifyable_object );
$obj->file( $stringifyable_object, $options_hash_ref );
$obj->file( $stringifyable_object, %options );

file( "/some/file.txt" );
file( "./my/directory" );

rmtree

Okay so this one takes a path, or an Module::Generic::File object, plus some optional parameters โ€” either as a list or as a hash reference โ€” and it removes the underlying path, whether it's got stuff inside it or not. So yeah, it's a recursive removal of everything inside the given directory path. Which means it has to be called on a directory object. ๐Ÿ—‘๏ธ

It takes these optional parameters:

  • dry_run โ€” If true, it will only pretend to remove the files recursively. Super useful for testing without actually deleting anything, because yikes.
  • keep_root โ€” If true, then rmtree will keep the directory and remove all of its content. If false, it will also remove the directory itself on top of its content. Defaults to false.
  • max_files โ€” Set the maximum number of files beyond which this function will refuse to perform. This is useful if you know you expect only a certain number of files within a directory and you don't want the program to hang, or possibly you don't want it to remove the directory because too many files within would be a sign of an error, etc.

You can also pass other parameters, like the ones File::Find uses, namely: bydepth, dangling_symlinks, follow, follow_fast, follow_skip, no_chdir, postprocess, preprocess, untaint, untaint_pattern and untaint_skip ๐Ÿซถ

See %options in File::Find for more info.

Example of usage:

$obj->rmtree( $some_dir_path );
$obj->rmtree( $some_dir_path, $options_hashref );
Module::Generic::File->rmtree( $some_dir_path );
Module::Generic::File->rmtree( $some_dir_path, $options_hashref );
rmtree( $some_dir_path );
rmtree( $some_dir_path, $options_hashref );
file( $some_dir_path )->rmtree;

Upon success it returns the current object. If it was called as a class function, an object is created, and it will be returned upon success too.

Heads up: it returns undef and sets an exception object if this is called on a file object. So like, don't do that ๐Ÿ™ˆ

rootdir

This returns an object representation of the system root directory. Very main character of it.

sys_tmpdir

Returns a new Module::Generic::File object representing the path to the system temporary directory, as returned by tmpdir in File::Spec ๐ŸŒธ

tempdir

Returns a new Module::Generic::File object representing a unique temporary directory.

tempfile

Returns a new Module::Generic::File object representing a unique temporary file.

It takes these optional parameters:

  • cleanup โ€” If true, this will enable the auto-remove option of the object. See auto_remove. See also unlink which is an alias.
  • dir โ€” A directory path to be used to create the temporary file within. This parameter takes precedence over tmpdir.
  • mode โ€” This is the mode used to open this temporary file. It is used as argument to open.
  • open โ€” If true, the temporary file will be opened. It defaults to false.
  • suffix or extension โ€” A suffix to add to the temporary file including leading dot, such as .txt. You can also specify the extension without any leading dot, such as txt.
  • tmpdir โ€” The path or object of a directory within which to create the temporary file. See also dir.
  • unlink โ€” If true, this will enable the auto-remove option of the object. See auto_remove. See also cleanup which is an alias.

๐Ÿ’€ EXCEPTION ๐Ÿ’€

This module does not croak or die (at least not intentionally ๐Ÿ˜ญ) โ€” that's a design choice, based on the belief that it's up to the main code of the script to control the flow and any interruptions.

When an error occurs, the methods under this package will return undef and set an Module::Generic::Exception object that you can grab using the inherited error in Module::Generic method.

For example:

my $f = Module::Generic::File->new( "/my/file.txt" );
$f->open || die( $f->error );

But here's the slay part โœจ: error in Module::Generic used to return undef, but it's smart now โ€” it knows, in a granular way (thanks to Wanted), the context of the caller. So if the method is chained, error in Module::Generic will instead return a Module::Generic::Null object so the chaining can keep going and you avoid that perl error you'd otherwise get: method called on an undefined value ๐ŸŽ€


๐Ÿฆ‹ OVERLOADING ๐Ÿฆ‹

Objects of this package are overloaded, and their stringification will call filename. So like, when you stringify it, that's what you get ๐Ÿ’…


๐ŸŒˆ SERIALISATION ๐ŸŒˆ

Serialisation by CBOR, Sereal and Storable::Improved (or the legacy Storable) is supported by this package. To that effect, the following subroutines are implemented: FREEZE, THAW, STORABLE_freeze and STORABLE_thaw โญ


๐Ÿงš VIRTUALISATION ๐Ÿงš

Okay this is the unique little superpower of this module: it lets you work with files in a different operating system context. Like, assuming your environment is a unix flavoured operating system, you can still literally do this:

use Module::Generic::File qw( file );
my $f = file( q{C:\Documents\Newsletters\Summer2018.pdf}, os => 'win32' );
$f->parent; # C:\Documents\Newsletters

Then switch to old Mac format:

my $f2 = $f->as( 'mac' );
say $f2; # Documents:Newsletters:Summer2018.pdf

Those file manipulations under different os, of course, have limitations โ€” since you cannot use real filesystem-related methods like open, print, etc, on, say, a win32 based file object in a Unix environment, because it would not work. No cap, it's just not gonna happen ๐Ÿ’€

๐Ÿงต THREAD & PROCESS SAFETY ๐Ÿ’…

okay bestie, gather round, because this is the part where Module::Generic::File gets its big โ€œI can survive all the chaosโ€ moment โœจ Itโ€™s designed to be fully thread-safe and process-safe, so your data integrity stays intact across Perl ithreads and mod_perlโ€™s threaded Multi-Processing Modules (MPMs) like Worker or Event. It combines system-level file locking (flock) with Perl-level synchronisation via Module::Generic::Global, giving you robust, system-wide thread-safe, and process-safe file operations. No cap ๐Ÿ’–

Key considerations for thread and process safety:

  • File Handles โ€” File handles made by open, write, append, and similar methods are per-object and exclusive to each thread or process. System-level file locking via lock (using flock in perlfunc) keeps concurrent access to file contents safe across all processes and threads on the system, while Module::Generic::Globalโ€™s fd_locks namespace coordinates lock state within a process:
use threads;
my $file = Module::Generic::File->new( "shared.txt", auto_remove => 1 );
my $obj = $file->open( '+>', autoflush => 1 );
my @threads = map
{
    threads->create(sub
    {
        my $fh = $obj->open( '+>>', { lock => 1, exclusive => 1 });
        if( !$fh )
        {
            warn( "Thread $_: Failed to open: ", $file->error );
            return(0);
        }
        $fh->write( "Thread $_: Hello\n" );
        $fh->close;
        return(1);
    });
} 1..5;
$_->join for( @threads );

This ensures thread-safe writes, with flock in perlfunc preventing concurrent file access system-wide and fd_locks making threads coordinate lock attempts, even across separate file instances. Lock failures (e.g., file already locked) return undef with an error object (HTTP code 423 for locked, 504 for timeout) ๐Ÿ”ฅ

  • Auto-Removal โ€” The auto_remove feature, used by tempfile and tempdir with cleanup, tracks files in the files_to_remove namespace of Module::Generic::Global, storing a boolean (1) to indicate removal eligibility. This repository is thread-safe, protected by Module::Generic::Globalโ€™s synchronisation (CORE::lock for ithreads or APR::ThreadRWLock for rare mod_perl non-threaded cases). In DESTROY, the module checks the instanceโ€™s auto_remove flag independently of the repository state, ensuring robust cleanup:
my $temp = Module::Generic::File->tempfile( cleanup => 1 );
$temp->auto_remove(1); # Thread-safe, removed in DESTROY

Files and directories are removed per-object in DESTROY, so no global cleanup at process exit is needed. Clean ๐Ÿ’…

  • File Locking โ€” File locking combines system-level and Perl-level synchronisation for system-wide thread- and process-safe file access:
    • System-Level (flock) โ€” lock and unlock use flock to enforce exclusive (LOCK_EX) or shared (LOCK_SH) locks on file descriptors, ensuring safe concurrent access to file contents across all processes and threads. If the file is already locked, lock returns undef with an error (code 423). A timeout option (e.g., timeout => 5) triggers an error (code 504) if the lock isnโ€™t acquired in time.
    • Perl-Level (Module::Generic::Global) โ€” The fd_locks namespace tracks lock state, storing metadata (lock flags, thread ID, timestamp), protected by Module::Generic::Globalโ€™s lock method. This ensures thread-safe coordination within a process, preventing redundant flock calls and maintaining consistent lock state across threads, even with separate file instances:
my $file = Module::Generic::File->new( "shared.txt" );
my $fh = $file->open( '>>', { lock => 1, exclusive => 1, timeout => 5 });
if( $fh )
{
    $fh->write( "Process $$: Data\n" );
    $fh->close;
}
else
{
    warn "Failed to lock: ", $file->error;
}
  • Memory Mapping โ€” The mmap method is designed for inter-process communication (e.g., with fork in perlfunc) and is not thread-safe for shared mappings. Avoid using mmap in threaded environments, because concurrent access to mapped memory can cause undefined behaviour ๐Ÿ˜ญ Use mmap with processes instead:
my $file = Module::Generic::File->tempfile( unlink => 1 );
$file->mmap( my $var, 10240, '+<' );
my $pid = fork();
if( $pid == 0 )
{
    $var = "Child data";
    exit;
}
waitpid( $pid, 0 );
print $var; # Child data

See the mmap method for detailed warnings. ๐Ÿ‘‘

  • Tied Scalars โ€” When callbacks are set via callback (e.g., for custom file operations), the scalar is tied to Module::Generic::Scalar::Tie. Tied scalar operations are thread-safe, as they rely on Module::Generic::Globalโ€™s synchronisation. However, callbacks themselves are not inherently thread-safe. If a callback accesses shared resources, you must implement additional synchronisation (e.g., using lock in perlfunc or Thread::Semaphore). Fr fr, donโ€™t skip that part ๐Ÿซถ
  • Process Safety โ€” File operations (e.g., open, write, delete) are safe across processes, relying on system-level file descriptors and flock in perlfunc for coordination. Use lock to ensure safe access to shared files:
my $file = Module::Generic::File->new( "shared.txt" );
my $fh = $file->open( '>>', { lock => 1, exclusive => 1 });
$fh->write( "Process $$: Data\n" );
$fh->close;
  • mod_perl Considerations โ€”
    • Prefork MPM โ€” File operations are per-process, with files_to_remove and fd_locks isolated by process ID. System-level flock in perlfunc ensures safe file access across processes.
    • Threaded MPMs (Worker/Event) โ€” Shared repositories are protected by Module::Generic::Globalโ€™s synchronisation (typically lock in perlfunc, or APR::ThreadRWLock in rare non-threaded Perl cases), and flock in perlfunc ensures file-level safety. Users should call Module::Generic::Global->cleanup_register in mod_perl handlers to clear repositories after requests, preventing memory leaks.
    • Thread-Unsafe Functions โ€” Avoid Perl functions like localtime in perlfunc, readdir in perlfunc, srand in perlfunc, or operations like chdir in perlfunc, umask in perlfunc, chroot in perlfunc in threaded MPMs, as they may affect all threads. Consult perlthrtut http://perldoc.perl.org/perlthrtut.html and mod_perl documentation https://perl.apache.org/docs/2.0/user/coding/coding.html#Thread_environment_Issues for details.
  • Cleanup โ€” Temporary files and directories (via tempfile, tempdir) are cleaned up thread-safely using the files_to_remove namespace. Ensure cleanup or auto_remove is enabled for automatic removal:
my $temp = Module::Generic::File->tempfile( cleanup => 1 );
$temp->mkpath; # Auto-removed in DESTROY

For debugging file operations in threaded or multi-process environments, use:

ipcs -m  # List shared memory segments (if mmap used)
ipcs -s  # List semaphores (if locking used)
ls -l /proc/$$/fd  # List open file descriptors

Note that the actual commands vary based on your Operating System. ๐ŸŒˆ


โœจ AUTHOR โœจ

Jacques Deguest <jack@deguest.jp> โ€” the icon behind this whole thing ๐Ÿ‘‘๐Ÿ’–


๐ŸŒธ SEE ALSO ๐ŸŒธ

  • Module::Generic::Finfo
  • Module::Generic
  • Module::Generic::Exception
  • Module::Generic::Number
  • Module::Generic::Scalar
  • Module::Generic::Array
  • Module::Generic::Null
  • Module::Generic::Boolean

Copyright (c) 2021-2024 DEGUEST Pte. Ltd.

You can use, copy, modify and redistribute this package and associated files under the same terms as Perl itself.


okay bestie, thatโ€™s the whole page ๐Ÿ’– source says perl v5.42.2, dated 2026-02-15 โ€” iconic, no notes ๐Ÿ’…โœจ

๐Ÿ“ฆ where this page comes from