我想检查一个文件名是否包含任何目录信息,最好不要使用像index($file_name,'/')!=-1
这样的系统相关黑客。我知道File::Spec
模块,但似乎找不到使用该模块做出此决定的方法。也许另一个模块会更好。以下是文件名的一些示例:
# This does not have directory info, so the test should fail (i.e., return false)
my $file_name1='abc.txt';
# These do have directory info, so the test should succeed (i.e., return true)
my $file_name2='dir/abc.txt';
my $file_name3='/home/me/abc.txt';
my $file_name4='~me/abc.txt';
答案 0 :(得分:3)
splitdir
将返回一个列表。在标量上下文中进行评估,它返回列表中的项目数。如果列表中有多个项目,那么您知道有一个目录分隔符。
use warnings;
use strict;
use File::Spec qw();
while (<DATA>) {
chomp;
if (File::Spec->splitdir($_) > 1) {
print 'PASS';
}
else {
print 'FAIL';
}
print ": $_\n";
}
__DATA__
abc.txt
dir/abc.txt
/home/me/abc.txt
~me/abc.txt
打印:
FAIL: abc.txt
PASS: dir/abc.txt
PASS: /home/me/abc.txt
PASS: ~me/abc.txt
答案 1 :(得分:1)
示例强>
($volume,$directories,$file) =
File::Spec->splitpath( $path );
splitpath 拆分卷,目录和文件名部分的路径。在没有音量概念的系统上,返回''表示音量。
答案 2 :(得分:1)
您必须使用File::Spec
才能获得适当的便携式结果。
如果复杂性困扰你,那么你应该编写自己的包含File::Spec
函数的库。
看起来像这样
档案PathLib.pm
package PathLib;
use strict;
use warnings;
require File::Spec;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(has_path);
sub has_path {
my ($volume, $path, $name) = File::Spec->splitpath($_[0]);
return ($path or $volume)
}
你可以像这样使用它。 (我目前正在使用Windows笔记本电脑,在我上桌前无法测试Unix版本,但我确信这对你有用。)
use strict;
use warnings;
use PathLib qw(has_path);
my @paths = qw{
C:\aa\bb\cc.txt
E:ee.txt
cc.txt
ee\
};
for (@paths) {
printf "%6s - %s\n", has_path($_) ? 'true' : 'false', $_;
}
<强>输出强>
true - C:\aa\bb\cc.txt
true - E:ee.txt
false - cc.txt
true - ee\
答案 3 :(得分:0)
在Perl中,/
始终保留为目录分隔符(旧Mac OS 系统 [6-9]除外,它坚持认为它是:
) 。但是,在其他操作系统中,也可以使用其他符号。例如,在Windows机器上,这两个引用同一目录:
$file = 'C:\this\that\foo.txt';
$file = "C:/this/that/foo.txt";
所以,你应该总是怀疑/
是一个目录说明符,除非你碰巧在旧的Mac上。而且,您还应该弄清楚当前路径分隔符在该系统上的位置,并查找该系统。
我希望File::Spec或File::Path可能有一些显示首选目录分隔符名称的函数或方法,但没有记录。
查看各种File::Spec
子模块的代码,我发现实际的文件分隔符是硬编码的,而且函数比我原先想象的要复杂得多。没有特殊的隐藏功能。 DRAT。
然而,好消息是File::Spec
是标准模块,因此没有理由担心它。它甚至包含在Perl 5.8.8中。您不必担心它可能没有安装。
我做了一个简单的测试:
#! /usr/bin/env perl
#
use strict;
use warnings;
use feature qw(say);
use File::Spec;
while ( my $file = <DATA> ) {
chomp $file;
my ( $volume, $directory, $file ) = File::Spec->splitpath( $file );
if ( $directory ) {
say qq('$volume' '$directory' '$file' contains directory stuff);
}
else {
say qq('$volume' '$directory' '$file' is pure file);
}
}
__DATA__
Foo/Bar.txt
/Bar.txt
Bar.txt/
Foo_Bar.txt
结果是:
'' 'Foo/' 'Bar.txt' contains directory stuff
'' '/' 'Bar.txt' contains directory stuff
'' 'Bar.txt/' '' contains directory stuff
'' '' 'Foo_Bar.txt' is pure file
似乎无论何时出现目录分隔符,该字符串都被视为文件。我想这是有道理的。
这是最终比您意识到的更复杂的任务之一(例如确定字符串是否是有效的电子邮件地址或数字)。最好的办法是使用File::Spec->split
并确保没有设置卷或目录。