Files and directories

    Always check the return code from for truthiness. If there's a failure, the result is in $!.

    Remove trailing linefeeds with chomp

    Lines read from a file have their trailing linefeed still attached. If you have a text file where the first line is

    1. Aaron

    "Aaron", is actually "Aaron\n", six characters. This code will fail:

    1. my $line = <$fh>;
    2. # won't reach here, because it's really "Aaron\n";
    3. }

    To remove the "\n", and any other trailing whitespace, call chomp.

    1. my $line = <$fh>;
    2. chomp $line;

    Now $line is five characters long.

    It's possible to change your input record separator, . It's only set to "\n" by default.

    Set $/ to read a paragraph at a time. Set $/ to undef to read the entire file at once. See for details.

    Slurp an entire file at once

    1. open (FILE,$filename) || die "Cannot open '$filename': $!";
    2. undef $/;
    3. my $file_as_string = <FILE>;

    or

    Of those two, choose the former. The second one reads all the lines into an array, and then glomps together a big string. The first one just reads into a string, without creating the intervening list of lines.

    The best way yet is like so:

    1. my $file_as_string = do {
    2. open( my $fh, $filename ) or die "Can't open $filename: $!";
    3. local $/ = undef;
    4. };

    The do() block returns the last value evaluated in the block. This method localizes the so that it gets set back outside the scope of the block. Without localizing $/, it retains the value being set to it and another piece of code might not be expecting it to have been set to undef.

    Here's another way:

    1. use File::Slurp qw( read_file );
    2. my $file_as_string = read_file( $filename );

    File::Slurp is a handy module for reading and writing a file at a time, and it does magic fast processing on the back end.

    Use standard shell globbing patterns to get a list of files.

    1. my @files = glob( "*" );
    1. my @files = grep { -f } glob( "*" );

    Use unlink to remove a file

    The Perl built-in delete deletes elements from a hash, not files from the filesystem.

    The term "unlink" comes from the Unix idea of removing a link to the file from the directory nodes.

    Even though Unix uses paths like /usr/local/bin and Windows uses C:\foo\bar\bat, you can still use forward slashes in your filenames.

    1. my $filename = 'C:/foo/bar/bat';
    2. open( my $fh, '<', $filename ) or die "Can't open $filename: $!";

    In this case, Perl magically changes the C:/foo/bar/bat to C:\foo\bar\bat before opening the file. This also prevents the problem where an unquoted backslash screws up a filename, as in:

    1. my $filename = "C:\tmp";

    In this case, contains five characters: 'C', ':', a tab character, 'm' and 'p'. Instead, it should have been written as one of:

    1. my $filename = 'C:\tmp';
    2. my $filename = "C:\\tmp";

    Or, you can let Perl take care of it for you with:


      Submit a PR to github.com/petdance/perl101