File::Spec behaves a bit unexpectedly if you split a 'path' which is actually a bare filename, and then put it back together after changing the directory portion (originally "") to an actual directory or path.
In this scenario catpath will put the relative path into the root directory - prepending a \ .
($v, $d, $f) = File::Spec->splitpath("barefile.txt");
$d = File::Spec->catdir($d, "archive");
$j = File::Spec->catpath($v, $d, $f);
$j is "\archive\barefile.txt" not "archive\barefile.txt".
Additionally, splitpath can't tell with c:\dir1\dir10\dir100 that dir100 is a directory, it will assume it is a filename. Unless a trailing slash is supplied, or an extra parameter , 1 .
The splitpath method in File::Spec appears to work thusly under Win32:
- Volume - drive letter and colon, or \\hostname\sharename
- Path - either "", or \, or will begin with \ and end with \
(path will be "" if it wasn't specified, eg c:blah.txt)
- Filename - the base file name
NB You can't avoid the 'catpath adds an extra slash after dir' issue by splitting dir into volume and dir first.