I recently started working with Perl as a requirement for an education class. Part of our homework is to open a text file, read some lines, and then close the file.
I created a folder on the desktop and put the required text files in it. I wrote the following code to open each file, read a line, and close it:
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";
}
When I run this script on Padre, the Perl IDE, I get this error:
C:./UsersJay
can't read open 'C:./UsersJay': at example.pl line 5
Press any key to continue.....
I don't understand why I'm getting this error unless I'm somehow mistakenly using \ instead of /, but when I right-click on a file in Windows Explorer, the path always shows up with backslashes, e.g. C:\something\something.
I tried changing the file path to use forward slashes as suggested by OnlineCop in the comments, but got a similar error:
C:/Users/Jay
can't read open 'C:/Users/Jay': at example.pl line 5
Press any key to continue.....
As others have observed, the problem is that your call to glob
glob("$dir/*.txt")
uses this definition of $dir
my $dir = 'C:\Users\Jay Zabaluski\Desktop\Shakespeare';
so the call is equivalent to this
glob('C:\Users\Jay Zabaluski\Desktop\Shakespeare/*.txt')
So the parameter has two components, C:\Users\Jay and Zabaluski\Desktop\Shakespeare/*.txt, which isn't at all what you meant.
The solution is to enclose the entire wildcard pattern in double quotes, so you could use the qq operator to define a new delimiter, different from ", that will interpolate embedded variables.
For example, try
my $glob_pattern = qq{"$dir/*.txt"};
say $glob_pattern;
and you will see that the parameter actually passed to glob is
"C:\Users\Jay Zabaluski\Desktop\Shakespeare/*.txt"
including the double quotes, which are essential.
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*")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With