1

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

4 回答 4

3

splitdir将返回一个列表。在标量上下文中评估,它返回列表中的项目数。如果列表中有超过 1 个项目,那么您就知道有一个目录分隔符。

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
于 2014-02-28T17:30:44.813 回答
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\
于 2014-02-28T18:03:52.223 回答
1

例子

($volume,$directories,$file) =
                       File::Spec->splitpath( $path );

splitpath 将路径拆分为卷、目录和文件名部分。在没有体积概念的系统上,返回 '' 表示体积。

于 2014-02-28T16:53:16.133 回答
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子模块的代码,发现实际的文件分隔符是硬编码的,功能比我想象的要复杂。没有特殊的隐藏功能。德拉特。

然而,好消息是这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并确保没有设置卷或目录。

于 2014-02-28T17:41:55.223 回答