在模式中使用带有空格的 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/*>
没有任何问题
我正在尝试从目录中压缩文件。它工作正常,除非文件名有空格。
由于 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/*>
没有任何问题