如何检查文件名是否包含目录信息?

时间:2014-02-28 16:46:35

标签: perl perl-module perlop

我想检查一个文件名是否包含任何目录信息,最好不要使用像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';

4 个答案:

答案 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::SpecFile::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并确保没有设置卷或目录。