Dangerous when using catfile for path ending in directory?

The module File::Spec

provides a way to create valid paths for different operating systems. It works as you would expect:

use strict;
use warnings;

use File::Spec;

my $file = 'ghi.xml';
my $path = File::Spec->catfile(('abc', 'def'), $file);
print $path;
# Windows: abc/def/ghi.xml

      

There is also a method available catdir

that will make the directory not a file path.

My problem is that I don't know in advance if $file

is a file name or a directory name. As far as I have checked, the results are still correct when using the dirname, e.g .:

use strict;
use warnings;

use File::Spec;

my $file = 'ghi';
my $path = File::Spec->catfile(('abc', 'def'), $file);
print $path;
# Windows: abc/def/ghi

      

But I'm wondering if this might cause problems. I assume yes, because I don't understand why the creators of the module would build two interfaces for the same functionality. However, I cannot find any further explanation in the documentation.

Can it be used catfile

to create paths to files as well as directories? If not, what are the caveats?

+3


source to share


1 answer


Difference catdir

and catfile

is usually very small ( depending on the operating system ). On UNIX, catfile

executes catdir

anyway for directory entries (for example, minus last (file)) and then appends part of the file. catdir

performs some path clearing logic. On the Windows platform, the differences are even smaller.

You can check the source of modules for different OS-es yourself .

The main point is that these routines do not have access to the file system, they just do some cleanup of logical paths.


Alternative:

If you don't like other OSs like UNIX-like (eg Linux, FreeBSD, Mac OS X, etc.) and Windows, I personally recommend using Path :: Tiny . From it doc:

This module provides a small, fast utility for manipulating the path file. This is more convenient to use than File :: Spec, and provides easy access to functions from several other kernel file processing modules. It aims to be smaller and faster than many CPAN alternatives, while helping people do a lot of the same in a consistent and less error-prone way.

Path :: Tiny doesn't try to work for anything other than Unix-like and Win32.

IMHO is one of the best CPAN modules - a real treasure. For example, to create a path, you have to use a method child

- again from the docs:

$file = path("/tmp")->child("foo.txt"); # "/tmp/foo.txt"
$file = path("/tmp")->child(@parts);

      

Returns a new Path :: Tiny object relative to the original. Works like catfile

or catdir

from file :: Spec, but doesn't care about file or directories.

In addition to the above, the Path :: Tiny module provides easy access to the contents of the file (also when handling Unicode) and each normal "path" "operation. Disadvantage: unfortunately, this is not a CORE module, eg you need to install it from CPAN.



EDIT

Is it safe to use catfile

for directories? For me: yes (but maybe some experts will know more or more). On unix,

  • catdir

    calls canonpath

    (which does some logical path cleanup).
  • catfile

    calls twice canonpath

    , once for part of the file and once for directories (if provided), and concatenates the two results. Concatenation can lead to some strange paths, but they are generally harmless.

On Windows the difference is even smaller, both will invoke the path cleanup routine.

Demo - The following script will generate many combinations of different parts and will use catdir

and catfile

(and even two options Path::Tiny

)

use strict;
use warnings;

use File::Spec::Functions;
use Path::Tiny;

my @parts = qw(x / /x /x/ /x// // //x //x/ //x// /./ /./x /x/./ );
my $cwidth=16;
print pr(qw(first second catdir catfile path-child path-list)), "\n";
print '-' x ($cwidth*6),"\n";
for my $first (map { s/x/first/r } @parts) {
    for my $second ( map { s/x/second/r } @parts) {
        print pr(
            $first,
            $second,
            catdir($first,$second),
            catfile($first,$second),
            path($first)->child($second),
            path($first,$second),
        ), "\n";
    }
}
sub pr {
    my $str;
    $str .= sprintf "%-${cwidth}s",$_ for @_;
    return $str;
}

      

It prints a long result. As you can see below, all paths are safe to use for directories and files, only some of the paths catfile

are not "nice".

"Path :: Tiny" results are clear and consistent. On the contrary, catfile

and catdir

will allow undefined parts (not shown in the demo) - and even with such erroneous arguments some results will be obtained, Path :: Tiny will die if you pass undef or null-string to its method child

.

first           second          catdir          catfile         path-child      path-list       
------------------------------------------------------------------------------------------------
first           second          first/second    first/second    first/second    first/second    
first           /               first           first//         first           first           
first           /second         first/second    first//second   first/second    first/second    
first           /second/        first/second    first//second   first/second    first/second    
first           /second//       first/second    first//second   first/second    first/second    
first           //              first           first//         first           first           
first           //second        first/second    first//second   first/second    first/second    
first           //second/       first/second    first//second   first/second    first/second    
first           //second//      first/second    first//second   first/second    first/second    
first           /./             first           first//         first           first           
first           /./second       first/second    first//second   first/second    first/second    
first           /second/./      first/second    first//second   first/second    first/second    
/               second          /second         /second         /second         /second         
/               /               /               //              /               /               
/               /second         /second         //second        /second         /second         
/               /second/        /second         //second        /second         /second         
/               /second//       /second         //second        /second         /second         
/               //              /               //              /               /               
/               //second        /second         //second        /second         /second         
/               //second/       /second         //second        /second         /second         
/               //second//      /second         //second        /second         /second         
/               /./             /               //              /               /               
/               /./second       /second         //second        /second         /second         
/               /second/./      /second         //second        /second         /second         
/first          second          /first/second   /first/second   /first/second   /first/second   
/first          /               /first          /first//        /first          /first          
/first          /second         /first/second   /first//second  /first/second   /first/second   
/first          /second/        /first/second   /first//second  /first/second   /first/second   
/first          /second//       /first/second   /first//second  /first/second   /first/second   
/first          //              /first          /first//        /first          /first          
/first          //second        /first/second   /first//second  /first/second   /first/second   
/first          //second/       /first/second   /first//second  /first/second   /first/second   
/first          //second//      /first/second   /first//second  /first/second   /first/second   
/first          /./             /first          /first//        /first          /first          
/first          /./second       /first/second   /first//second  /first/second   /first/second   
/first          /second/./      /first/second   /first//second  /first/second   /first/second   
/first/         second          /first/second   /first/second   /first/second   /first/second   
/first/         /               /first          /first//        /first          /first          
/first/         /second         /first/second   /first//second  /first/second   /first/second   
/first/         /second/        /first/second   /first//second  /first/second   /first/second   
/first/         /second//       /first/second   /first//second  /first/second   /first/second   
/first/         //              /first          /first//        /first          /first          
/first/         //second        /first/second   /first//second  /first/second   /first/second   
/first/         //second/       /first/second   /first//second  /first/second   /first/second   
/first/         //second//      /first/second   /first//second  /first/second   /first/second   
/first/         /./             /first          /first//        /first          /first          
/first/         /./second       /first/second   /first//second  /first/second   /first/second   
/first/         /second/./      /first/second   /first//second  /first/second   /first/second   
/first//        second          /first/second   /first/second   /first/second   /first/second   
/first//        /               /first          /first//        /first          /first          
/first//        /second         /first/second   /first//second  /first/second   /first/second   
/first//        /second/        /first/second   /first//second  /first/second   /first/second   
/first//        /second//       /first/second   /first//second  /first/second   /first/second   
/first//        //              /first          /first//        /first          /first          
/first//        //second        /first/second   /first//second  /first/second   /first/second   
/first//        //second/       /first/second   /first//second  /first/second   /first/second   
/first//        //second//      /first/second   /first//second  /first/second   /first/second   
/first//        /./             /first          /first//        /first          /first          
/first//        /./second       /first/second   /first//second  /first/second   /first/second   
/first//        /second/./      /first/second   /first//second  /first/second   /first/second   
//              second          /second         /second         /second         /second         
//              /               /               //              /               /               
//              /second         /second         //second        /second         /second         
//              /second/        /second         //second        /second         /second         
//              /second//       /second         //second        /second         /second         
//              //              /               //              /               /               
//              //second        /second         //second        /second         /second         
//              //second/       /second         //second        /second         /second         
//              //second//      /second         //second        /second         /second         
//              /./             /               //              /               /               
//              /./second       /second         //second        /second         /second         
//              /second/./      /second         //second        /second         /second         
//first         second          /first/second   /first/second   /first/second   /first/second   
//first         /               /first          /first//        /first          /first          
//first         /second         /first/second   /first//second  /first/second   /first/second   
//first         /second/        /first/second   /first//second  /first/second   /first/second   
//first         /second//       /first/second   /first//second  /first/second   /first/second   
//first         //              /first          /first//        /first          /first          
//first         //second        /first/second   /first//second  /first/second   /first/second   
//first         //second/       /first/second   /first//second  /first/second   /first/second   
//first         //second//      /first/second   /first//second  /first/second   /first/second   
//first         /./             /first          /first//        /first          /first          
//first         /./second       /first/second   /first//second  /first/second   /first/second   
//first         /second/./      /first/second   /first//second  /first/second   /first/second   
//first/        second          /first/second   /first/second   /first/second   /first/second   
//first/        /               /first          /first//        /first          /first          
//first/        /second         /first/second   /first//second  /first/second   /first/second   
//first/        /second/        /first/second   /first//second  /first/second   /first/second   
//first/        /second//       /first/second   /first//second  /first/second   /first/second   
//first/        //              /first          /first//        /first          /first          
//first/        //second        /first/second   /first//second  /first/second   /first/second   
//first/        //second/       /first/second   /first//second  /first/second   /first/second   
//first/        //second//      /first/second   /first//second  /first/second   /first/second   
//first/        /./             /first          /first//        /first          /first          
//first/        /./second       /first/second   /first//second  /first/second   /first/second   
//first/        /second/./      /first/second   /first//second  /first/second   /first/second   
//first//       second          /first/second   /first/second   /first/second   /first/second   
//first//       /               /first          /first//        /first          /first          
//first//       /second         /first/second   /first//second  /first/second   /first/second   
//first//       /second/        /first/second   /first//second  /first/second   /first/second   
//first//       /second//       /first/second   /first//second  /first/second   /first/second   
//first//       //              /first          /first//        /first          /first          
//first//       //second        /first/second   /first//second  /first/second   /first/second   
//first//       //second/       /first/second   /first//second  /first/second   /first/second   
//first//       //second//      /first/second   /first//second  /first/second   /first/second   
//first//       /./             /first          /first//        /first          /first          
//first//       /./second       /first/second   /first//second  /first/second   /first/second   
//first//       /second/./      /first/second   /first//second  /first/second   /first/second   
/./             second          /second         /second         /second         /second         
/./             /               /               //              /               /               
/./             /second         /second         //second        /second         /second         
/./             /second/        /second         //second        /second         /second         
/./             /second//       /second         //second        /second         /second         
/./             //              /               //              /               /               
/./             //second        /second         //second        /second         /second         
/./             //second/       /second         //second        /second         /second         
/./             //second//      /second         //second        /second         /second         
/./             /./             /               //              /               /               
/./             /./second       /second         //second        /second         /second         
/./             /second/./      /second         //second        /second         /second         
/./first        second          /first/second   /first/second   /first/second   /first/second   
/./first        /               /first          /first//        /first          /first          
/./first        /second         /first/second   /first//second  /first/second   /first/second   
/./first        /second/        /first/second   /first//second  /first/second   /first/second   
/./first        /second//       /first/second   /first//second  /first/second   /first/second   
/./first        //              /first          /first//        /first          /first          
/./first        //second        /first/second   /first//second  /first/second   /first/second   
/./first        //second/       /first/second   /first//second  /first/second   /first/second   
/./first        //second//      /first/second   /first//second  /first/second   /first/second   
/./first        /./             /first          /first//        /first          /first          
/./first        /./second       /first/second   /first//second  /first/second   /first/second   
/./first        /second/./      /first/second   /first//second  /first/second   /first/second   
/first/./       second          /first/second   /first/second   /first/second   /first/second   
/first/./       /               /first          /first//        /first          /first          
/first/./       /second         /first/second   /first//second  /first/second   /first/second   
/first/./       /second/        /first/second   /first//second  /first/second   /first/second   
/first/./       /second//       /first/second   /first//second  /first/second   /first/second   
/first/./       //              /first          /first//        /first          /first          
/first/./       //second        /first/second   /first//second  /first/second   /first/second   
/first/./       //second/       /first/second   /first//second  /first/second   /first/second   
/first/./       //second//      /first/second   /first//second  /first/second   /first/second   
/first/./       /./             /first          /first//        /first          /first          
/first/./       /./second       /first/second   /first//second  /first/second   /first/second   
/first/./       /second/./      /first/second   /first//second  /first/second   /first/second   

      

+4


source







All Articles