当我在名称中有空格的目录上使用glob时,为什么我不能打开文件?

时间:2014-11-12 16:02:25

标签: perl

我最近开始使用Perl作为教育课程的要求。我们的部分功课是打开文本文件,读取一些行,然后关闭文件。

我在桌面上创建了一个文件夹,并将所需的文本文件放入其中。我编写了以下代码来打开每个文件,读取一行并关闭它:

my $dir = 'C:\Users\Jay Zabaluski\Desktop\Shakespeare';

opendir (DIR, $dir) or die "cannot opendir $dir";

foreach my $fp (glob("$dir/*.txt")) {

  printf "%s\n", $fp;

  open my $fh, "<", $fp or die "can't read open '$fp': $OS_ERROR";
  my $firstLine = <$fh>;
  print "$firstLine\n";

  close $fh or die "can't read close '$fp': $OS_ERROR";
}

当我在Padre,Perl IDE上运行此脚本时,我收到此错误:

C:./UsersJay
can't read open 'C:./UsersJay': at example.pl line 5
Press any key to continue.....

我不明白为什么我收到此错误,除非我错误地使用\而不是/,但是当我在Windows资源管理器中右键单击某个文件时,路径总是出现反斜杠,例如C:\something\something

我尝试按照注释中的OnlineCop的建议更改文件路径以使用正斜杠,但得到了类似的错误:

C:/Users/Jay
can't read open 'C:/Users/Jay': at example.pl line 5
Press any key to continue.....

2 个答案:

答案 0 :(得分:3)

正如其他人所观察到的那样,问题在于您拨打glob

glob("$dir/*.txt")

使用$dir

的定义
my $dir = 'C:\Users\Jay Zabaluski\Desktop\Shakespeare';

所以这个电话等同于这个

glob('C:\Users\Jay Zabaluski\Desktop\Shakespeare/*.txt')

所以参数有两个组件,C:\Users\JayZabaluski\Desktop\Shakespeare/*.txt,这完全不是你想要的。

解决方案是将整个通配符模式用双引号括起来,这样你就可以使用qq运算符来定义一个与"不同的新分隔符,它将插入嵌入变量。

例如,尝试

my $glob_pattern = qq{"$dir/*.txt"};
say $glob_pattern;

你会看到传递给glob的参数实际

"C:\Users\Jay Zabaluski\Desktop\Shakespeare/*.txt"

包括双引号,这是必不可少的。

答案 1 :(得分:2)

foreach my $fp (glob qq("$dir/*.txt")) {

perldoc -f glob

 
Note that "glob" splits its arguments on whitespace and treats
each segment as separate pattern. As such, "glob("*.c *.h")"
matches all files with a .c or .h extension. The expression
"glob(".* *")" matches all files in the current working directory.
If you want to glob filenames that might contain whitespace,
you'll have to use extra quotes around the spacey filename to
protect it. For example, to glob filenames that have an "e"
followed by a space followed by an "f", use either of:
            @spacies = <"*e f*">;
            @spacies = glob '"*e f*"';
            @spacies = glob q("*e f*");
 If you had to get a variable through, you could do this:
            @spacies = glob "'*${var}e f*'";
            @spacies = glob qq("*${var}e f*")