【问题标题】:Using Perl glob with spaces in the pattern在模式中使用带空格的 Perl glob
【发布时间】:2015-08-27 22:31:37
【问题描述】:

我正在尝试从目录压缩文件。它工作得很好,除非文件名有空格。

由于glob 将其参数拆分为空格,我也尝试了bsd_glob,但没有成功。

如何处理文件名中的空格?我正在寻找检索所有文件。

#Directory of focus
my $log = 'C:/Users/me/Desktop/log';

my @files = bsd_glob( $log.'/*.*' );

#Copy contents to new directory to be zipped
foreach my $file (@files) {
   copy($file, $logout) or die
   "Failed to copy $file: $!\n";
}

复制失败

# Create Child tmp
my $out = 'C:/Users/me/Desktop/out';
mkdir $out;

# Directory of focus
my $log = 'C:/Users/me/Desktop/log';

opendir (DIR, $log) or die $!;

while ( my $file = readdir(DIR) ) {
    next if $file =~ /^\./;
    #print "$file\n";
    copy($file, $out) or die "Failed to copy $file: $!\n";
}

closedir (DIR);

【问题讨论】:

    标签: perl activestate


    【解决方案1】:

    您的代码中没有任何冲突,因为空格在 glob 找到的文件中无关紧要,仅在您作为参数传递给它的模式中。我注意到你在Matt Jacob's post的评论中写道

    对不起,这个过程有效。谢谢!显然文件是在别处打开的

    所以我想这一直是问题所在。但我认为如果我解释如何让glob 处理包含空格的模式会很有用

    glob 带空格的行为

    我会写

    my @files = glob "$log/*.*"
    

    因为我认为它更清晰,但是您传递给glob 的字符串是C:/Users/me/Desktop/log/*.* 没有空格,所以glob 很好

    如果路径中有空格,那么你是对的 - glob 会在这些空格处拆分并将每个部分视为单独的参数。说你有

    my @files = glob "C:/Program Files/*"
    

    那么您将获得列表('C:/Program'),因为glob 仅在模式中有通配符时才检查文件是否存在。所以我们取回了第一部分C:/Program,它没有通配符,但第二部分没有更多贡献,因为没有匹配Files/*的文件

    使用引号的解决方案

    在这种情况下,解决方案是将包含空格的模式包含在一对引号中——单引号或双引号。所以无论是

    my @files = glob "'C:/Program Files/*'"
    

    my @files = glob '"C:/Program Files/*"'
    

    会正常工作。但是,如果您想插入像 C:/Users/me/Desktop/out 这样的路径,那么最外面的引号必须是双引号。在你的情况下看起来像

    my $log = 'C:/Users/me/Desktop/log';
    my @files = glob "'$log/*.*'";
    

    但我更喜欢像这样使用替代的qq 运算符

    my $log = 'C:/Users/me/Desktop/log';
    my @files = glob qq{"$log/*.*"};
    

    使用 bsd_glob 的解决方案

    正如您在问题中指出的那样,替代方法是添加

    use File::Glob 'bsd_glob'
    

    到您的代码顶部并改用bsd_glob 函数,它将模式中的空格与任何其他字符相同,并且不会拆分它们。

    或者如果你有

    use File::Glob ':bsd_glob'
    

    (注意附加的冒号)然后标准的glob 调用的行为方式与bsd_glob 相同,这允许您像这样使用glob 的尖括号形式

    my @files = <C:/Program Files/*>
    

    没有任何问题

    【讨论】:

      【解决方案2】:

      不要使用glob。请改用readdir(如果需要递归,请使用File::Find)。

      opendir (my $dh, $log) or die $!;
      
      while (my $file = readdir($dh)) {
          next if $file =~ /^\./;
          copy("$log/$file", $out) or die "Failed to copy $file: $!\n";
      }
      
      closedir($dh);
      

      【讨论】:

      • 好的,看起来我也可以使用 readdir 进行迭代。谢谢,马特。
      • 只记得过滤掉点(...)并检查条目是文件。我链接到的文档有做这些事情的例子。
      • 我能够过滤掉隐藏文件并获得正确的计数,但是当我复制(file, outputloc) 时它无法复制。你知道为什么吗?
      • 您是否在目录前面添加了完整路径?
      • 我将进行编辑以显示。等一下。非常感谢,非常感谢您的帮助
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-16
      • 1970-01-01
      • 2014-07-04
      • 1970-01-01
      • 2019-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多