在模式中使用带有空格的 Perl glob

Using Perl glob with spaces in the pattern

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

由于 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);

不要使用 glob。如果需要递归,请使用 readdir instead (or 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);

您的代码中没有任何冲突,因为 spaces 在 glob 找到的文件中无关紧要 ,仅在您传递的模式中将其作为参数。我注意到您在

的评论中写道

I'm sorry, the process works. Thank you! Apparently the file is opened elsewhere

所以我认为这一直是问题所在。但是我认为如果我解释如何让 glob 来处理包含 spaces

的模式会很有用

glob 与 space 的行为

我会写

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

因为我认为它更清楚,但是您传递给 glob 的字符串是 C:/Users/me/Desktop/log/*.*,它没有 space,所以 glob 没问题

如果你在某处的路径中有一个 space 那么你是对的 - glob 会在那些 space 处拆分并将每个部分视为一个单独的参数。假设你有

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

那么你会得到列表 ('C:/Program') 因为 glob 只有在模式中有通配符时才会检查文件是否存在。所以我们得到没有通配符的第一部分 C:/Program,但第二部分没有任何贡献,因为没有文件匹配 Files/*

使用引号的解决方案

这种情况下的解决方案是将包含 space 的模式用一对引号引起来——单引号或双引号。所以

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 函数,它将模式中的 space 视为与任何其他字符相同,并且不会在它们上拆分。

或者如果你有

use File::Glob ':bsd_glob'

(注意额外的冒号)那么标准 glob 调用的行为方式与 bsd_glob 相同,这允许您像这样使用 glob 的尖括号形式

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

没有任何问题