将 catfile 用于以目录结尾的路径时有危险吗?
Danger when using catfile for a path ending in a directory?
File::Spec
模块提供了一种创建跨OS 有效路径的方法。正如人们所期望的那样工作:
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
方法 catdir
也可用,它会生成目录 - 而不是文件路径。
我的问题是我事先不知道 $file
是文件名还是目录名。据我测试,使用目录名时结果仍然正确,例如:
use strict;
use warnings;
use File::Spec;
my $file = 'ghi';
my $path = File::Spec->catfile(('abc', 'def'), $file);
print $path;
# Windows: abc/def/ghi
但我想知道这是否会导致问题。我假设 yes 因为我不明白为什么模块的创建者会为相同的功能构建两个接口。但是,我在文档中找不到任何进一步的解释。
使用 catfile
创建文件和目录路径是否安全?如果没有,注意事项是什么?
catdir
和catfile
的区别通常很小(取决于使用的OS)。在 UNIX 上,catfile
无论如何都会对 目录 元素执行 catdir
(例如减去最后的(文件)部分),然后附加 文件 部分。 catdir
执行一些路径清理逻辑。在 windows 平台上差异更小。
您可以自己查看 source of the module(s) for the different OS-es。
主要是:这些例程不进行任何文件系统访问,只是进行一些逻辑路径清理。
选择:
如果您不关心其他 OS-es 作为类 UNIX(例如 Linux、FreeBSD、Mac OS X 等。) 和Windows,我个人推荐使用Path::Tiny模块。来自它的文档:
This module provides a small, fast utility for working with file
paths. It is friendlier to use than File::Spec and provides easy
access to functions from several other core file handling modules. It
aims to be smaller and faster than many alternatives on CPAN, while
helping people do many common things in consistent and less
error-prone ways.
Path::Tiny does not try to work for anything except Unix-like and
Win32 platforms.
恕我直言 - 它是 CPAN 上最好的模块之一 - 真正的宝藏。例如,对于路径创建,您应该使用 child
方法 - 再次来自文档:
$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 without caring about file
or directories.
除上述内容外,Path::Tiny 模块提供对文件内容的轻松访问(也使用 unicode 处理)和每个常用的 "path" 操作。缺点:不幸的是,它不是核心模块,例如您需要从 CPAN 安装它。
编辑
对目录使用 catfile
安全吗?由我:是(但也许一些专家会知道其他或更多)。在 unix 上,
catdir
调用 canonpath
(执行一些逻辑路径清理)。
catfile
调用 canonpath
两次,一次针对 file 部分,一次针对 directories (如果提供),并将两个结果连接起来。串联可能会产生一些看起来很奇怪的路径,但它们通常是无害的。
在 Windows 上,差异更小,两者都会调用路径清理例程。
演示 - 以下脚本将生成许多不同部分的组合,并将使用 catdir
和 catfile
(甚至 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;
}
它打印了一个很长的结果。正如您在下面看到的,所有路径都可以安全地用于目录和文件,只是来自 catfile
的一些路径不是 "nice".
两个 "Path::Tiny" 结果清晰一致。相反,catfile
和 catdir
将允许使用未定义的部分,(未在演示中显示)- 即使在这种错误的参数中 也会产生一些结果 , Path::Tiny 如果你将 undef 或 null 字符串传递给它的 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
File::Spec
模块提供了一种创建跨OS 有效路径的方法。正如人们所期望的那样工作:
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
方法 catdir
也可用,它会生成目录 - 而不是文件路径。
我的问题是我事先不知道 $file
是文件名还是目录名。据我测试,使用目录名时结果仍然正确,例如:
use strict;
use warnings;
use File::Spec;
my $file = 'ghi';
my $path = File::Spec->catfile(('abc', 'def'), $file);
print $path;
# Windows: abc/def/ghi
但我想知道这是否会导致问题。我假设 yes 因为我不明白为什么模块的创建者会为相同的功能构建两个接口。但是,我在文档中找不到任何进一步的解释。
使用 catfile
创建文件和目录路径是否安全?如果没有,注意事项是什么?
catdir
和catfile
的区别通常很小(取决于使用的OS)。在 UNIX 上,catfile
无论如何都会对 目录 元素执行 catdir
(例如减去最后的(文件)部分),然后附加 文件 部分。 catdir
执行一些路径清理逻辑。在 windows 平台上差异更小。
您可以自己查看 source of the module(s) for the different OS-es。
主要是:这些例程不进行任何文件系统访问,只是进行一些逻辑路径清理。
选择:
如果您不关心其他 OS-es 作为类 UNIX(例如 Linux、FreeBSD、Mac OS X 等。) 和Windows,我个人推荐使用Path::Tiny模块。来自它的文档:
This module provides a small, fast utility for working with file paths. It is friendlier to use than File::Spec and provides easy access to functions from several other core file handling modules. It aims to be smaller and faster than many alternatives on CPAN, while helping people do many common things in consistent and less error-prone ways.
Path::Tiny does not try to work for anything except Unix-like and Win32 platforms.
恕我直言 - 它是 CPAN 上最好的模块之一 - 真正的宝藏。例如,对于路径创建,您应该使用 child
方法 - 再次来自文档:
$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
orcatdir
from File::Spec, but without caring about file or directories.
除上述内容外,Path::Tiny 模块提供对文件内容的轻松访问(也使用 unicode 处理)和每个常用的 "path" 操作。缺点:不幸的是,它不是核心模块,例如您需要从 CPAN 安装它。
编辑
对目录使用 catfile
安全吗?由我:是(但也许一些专家会知道其他或更多)。在 unix 上,
catdir
调用canonpath
(执行一些逻辑路径清理)。catfile
调用canonpath
两次,一次针对 file 部分,一次针对 directories (如果提供),并将两个结果连接起来。串联可能会产生一些看起来很奇怪的路径,但它们通常是无害的。
在 Windows 上,差异更小,两者都会调用路径清理例程。
演示 - 以下脚本将生成许多不同部分的组合,并将使用 catdir
和 catfile
(甚至 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;
}
它打印了一个很长的结果。正如您在下面看到的,所有路径都可以安全地用于目录和文件,只是来自 catfile
的一些路径不是 "nice".
两个 "Path::Tiny" 结果清晰一致。相反,catfile
和 catdir
将允许使用未定义的部分,(未在演示中显示)- 即使在这种错误的参数中 也会产生一些结果 , Path::Tiny 如果你将 undef 或 null 字符串传递给它的 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