perlpipe has asked for the wisdom of the Perl Monks concerning the following question:

On my windows 7 system I have a directory named:

E:\Music\Ray LaMontagne\2010 - God Willin' & The Creek Don't Rise

In my program the variable $fn contains the above string. When I do a stat on that variable I get an undefined return value. The same with -d or -f as in:

 @s=stat $fn;

or

if (-d $fn) {print "Directory"}

Is there any way to get the stat to work?

I am running activestate perl 5.16.2 with a "use 5.12.0".

Replies are listed 'Best First'.
Re: stat on file name containing single quotes
by kennethk (Abbot) on Jul 30, 2015 at 21:50 UTC
    I don't think the string contains what you think it does.
    #!/usr/bin/perl use strict; use warnings; my $fn = q{C:\Music\Ray LaMontagne\2010 - God Willin' & The Creek Don' +t Rise}; print -d $fn;
    works for me. I'm betting you didn't escape your backslashes in your double quotes. Do you have warnings enabled?

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      You're right. My dumb text editor added the .txt ext and dumb me didn't notice it.

      c:\test>Perl-1.pl C:\Music\Ray LaMontagne\2010 - God Willin' & The Creek Don't Rise.txt $VAR1 = [ 2, 0, 33206, 1, 0, 0, 2, 0, 1438291895, 1438291895, 1438291895, '', '' ];
Re: stat on file name containing single quotes
by fishmonger (Chaplain) on Jul 30, 2015 at 21:56 UTC

    I suspect that you're assigning $fn like this:
    my $fn = "E:\Music\Ray LaMontagne\2010 - God Willin' & The Creek Don't Rise";

    If that's the case and you have warnings enabled, you should be receiving a warning like this.

    Unrecognized escape \M passed through at C:\test\Perl-1.pl line 9. Unrecognized escape \R passed through at C:\test\Perl-1.pl line 9.

      Not to mention octal character  \201 which is interpolated quite silently:

      c:\@Work\Perl\monks>perl -wMstrict -le "my $fn = qq{E:\Music\Ray LaMontagne\2010 - God Willin' & The Creek Do +n't Rise}; print qq{'$fn'}; " Unrecognized escape \M passed through at -e line 1. Unrecognized escape \R passed through at -e line 1. 'E:MusicRay LaMontagneü0 - God Willin' & The Creek Don't Rise'


      Give a man a fish:  <%-(-(-(-<

      A simple workaround is to use forward slashes instead of backslashes. Windows accepts them without problems. The only place where forward slashes may become problematic is on the command line of external programs. In that case, a simple tr|/|\\| helps.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: stat on file name containing single quotes
by fishmonger (Chaplain) on Jul 30, 2015 at 21:28 UTC

    Exactly how are you assigning $fn.

    Please post a short but complete test script that demonstrates the problem.

      I was just going to ask that after I quickly tested the following successfully on Windows.

      use strict; use warnings; my $fn = "this 'is' a text file.txt"; my @a = stat $fn; print "$_\n" for @a;

        Yes, that works, but when you start adding the full path which also includes spaces, it fails.

        The issue is with getting the quoting and escaping set correctly for the shell.

        c:\test>dir "C:\Music\Ray LaMontagne" Volume in drive C has no label. Volume Serial Number is 4CD3-F30A Directory of C:\Music\Ray LaMontagne 07/30/2015 02:31 PM <DIR> . 07/30/2015 02:31 PM <DIR> .. 07/30/2015 02:31 PM 0 2010 - God Willin' & The Creek +Don't Rise.txt 1 File(s) 0 bytes 2 Dir(s) 938,700,210,176 bytes free c:\test>type Perl-1.pl #!/usr/bin/perl use 5.010; use strict; use warnings; use Data::Dumper; # I created this full path for the test my $fn = q(C:\Music\Ray LaMontagne\2010 - God Willin' & The Creek Don' +t Rise); print $fn, $/; #my $fn = "this 'is' a text file.txt"; my @s = stat $fn; print Dumper \@s; c:\test>Perl-1.pl C:\Music\Ray LaMontagne\2010 - God Willin' & The Creek Don't Rise $VAR1 = [];

        I've delt with this issue before and always need to run a bunch of tests to get the quoting/escaping correct.

      The line is in fact read from a text file. Here is some simplified code that reads from a file containing only the one line I am talking about here.

      use 5.12.0; use strict; use warnings; use Carp; open IN,"<DirList.txt"; my $fn=<IN>; chomp $fn; say $fn; my @st=stat $fn; if (@st) { say "Array defined"; } else { say "Array undefined"; }

      The result is:

      E:\Music\Ray LaMontagne\2010 - God Willin' & The Creek Don't Rise Array undefined
        Note that the "chomp" and the "say" don't seem to have a problem with the variable $fn containing a string that has single quotes and backslashes in it. So I was expecting "stat" to not have a problem. Obviously I was wrong.

        Further testing indicates that we are getting side tracked by the single quote issue. That is if we change the input file so it specifies a file or directory name that contains extended ascii as in an accented e (0x82) then we get the same result with the stat function. Windows accepts these name. stat does not. The name I tested with came from my Adobe Acrobat installation in C:\Program Files (x86).

        Here is the modified program run against an updated input file.

        use 5.12.0; use strict; use warnings; use Carp; open IN,"<DirList2.txt"; my $fn=<IN>; chomp $fn; my @st=stat $fn; if (@st) { say "Array defined"; } else { say "Array undefined"; }

        The input was:

        C:\Program Files (x86)\Adobe\Acrobat 10.0\Acrobat\Sequences\FRA\Cr0xc20x82er des fichiers PDF accessibles.sequ

        The output was:

        Array undefined

Re: stat on file name containing single quotes
by Anonymous Monk on Jul 31, 2015 at 00:00 UTC
    use Win32::Unicode qw/ -native /; if( file_type( 'd', $fullpath ) ){ die "uhoh" }
Re: stat on file name containing single quotes
by james28909 (Deacon) on Jul 31, 2015 at 01:30 UTC
    When I were running a script once, I was having path problems, space in paths to be more specific. I solved the spaces issue by using
    "\"$var\""

    I dont know if it will help you though, but I reckon its worth a try :)

    EDIT: please let me go check my old code though because i need to see exactly what all was concatenated in $var.
    EDIT2: Please disregard, I was thinking about feeding another program a quoted string and the above was my solution. I am sure it will not work for your situation.

      EDIT2: Please disregard, I was thinking about feeding another program a quoted string and the above was my solution. I am sure it will not work for your situation.

      FYI, Win32::ShellQuote, system_detached