Search code examples
windowsperliobackslashpath-separator

Why doesn't this path work to open a Windows file in PERL?


I tried to play with Strawberry Perl, and one of the things that stumped me was reading the files.

I tried to do:

open(FH, "D:\test\numbers.txt");

But it can not find the file (despite the file being there, and no permissions issues).

An equivalent code (100% of the script other than the filename was identical) worked fine on Linux.


Solution

  • As per Perl FAQ 5, you should be using forward slashes in your DOS/Windows filenames (or, as an alternative, escaping the backslashes).

    Why can't I use "C:\temp\foo" in DOS paths? Why doesn't `C:\temp\foo.exe` work?

    Whoops! You just put a tab and a formfeed into that filename! Remember that within double quoted strings ("like\this"), the backslash is an escape character. The full list of these is in Quote and Quote-like Operators in perlop. Unsurprisingly, you don't have a file called "c:(tab)emp(formfeed)oo" or "c:(tab)emp(formfeed)oo.exe" on your legacy DOS filesystem.

    Either single-quote your strings, or (preferably) use forward slashes. Since all DOS and Windows versions since something like MS-DOS 2.0 or so have treated / and \ the same in a path, you might as well use the one that doesn't clash with Perl--or the POSIX shell, ANSI C and C++, awk, Tcl, Java, or Python, just to mention a few. POSIX paths are more portable, too.

    So your code should be open(FH, "D:/test/numbers.txt"); instead, to avoid trying to open a file named "D:<TAB>est\numbers.txt"


    As an aside, you could further improve your code by using lexical (instead of global named) filehandle, a 3-argument form of open, and, most importantly, error-checking ALL your IO operations, especially open() calls:

    open(my $fh, "<", "D:/test/numbers.txt") or die "Could not open file: $!";
    

    Or, better yet, don't hard-code filenames in IO calls (the following practice MAY have let you figure out a problem sooner):

    my $filename = "D:/test/numbers.txt";
    open(my $fh, "<", $filename) or die "Could not open file $filename: $!";