2
if (!-d $logsDir) {
    print "LOGSDIR: [$logsDir] does not exist\n";
}
else {
    print "LOGSDIR: [$logsDir] exists\n";
}

I am passing the following value to $logsDir from command line and getting the following output

LOGSDIR: [c:\temp><] exists

I do have C:\temp. I know temp>< is not a valid folder name on windows. But shouldn't -d give me the correct answer saying that this directory does not exist?

thanks

Thanks for the edit and the answer. Here is the modified code and output, it still doesn't work.

use strict;
use warnings;

my $logsDir = $ARGV[0];

if (-d $logsDir) {
    print "$logsDir exists";
} else {
    print "$logsDir does not exist!";
}

__END__

Results 
>perl test60.pl c:\temp
c:\temp exists

>perl test60.pl c:\temp^<^>
c:\temp<> exists

Thanks to melporne, I also tried this

C:\Users\XXXX>dir C:\temp
 Volume in drive C is System
 Volume Serial Number is XXXX

 Directory of C:\temp

09/16/2019  12:07 AM    <DIR>          .
09/16/2019  12:07 AM    <DIR>          ..
07/03/2019  11:50 PM               765 abcd.txt
07/04/2019  12:24 AM               765 efgh.txt
07/04/2019  12:41 AM               765 efgh.txt

and so on

C:\Users\XXXX>dir C:\temp^<^>
 Volume in drive C is System
 Volume Serial Number is XXXX

 Directory of C:\

09/16/2019  12:07 AM    <DIR>          Temp
09/15/2019  05:33 PM    <DIR>          temp1
11/19/2018  06:06 PM    <DIR>          Temp;
09/15/2019  12:31 AM    <DIR>          temparchive
               0 File(s)              0 bytes
               4 Dir(s)  yyyyyyyyyyy bytes free

I do have the above folders, so it looks like it is treating it as temp*. The above result is exactly similar to this

C:\Users\XXXX>dir C:\temp*
 Volume in drive C is System
 Volume Serial Number is XXXX

 Directory of C:\

09/16/2019  12:07 AM    <DIR>          Temp
09/15/2019  05:33 PM    <DIR>          temp1
11/19/2018  06:06 PM    <DIR>          Temp;
09/15/2019  12:31 AM    <DIR>          temparchive
               0 File(s)              0 bytes
               4 Dir(s)  yyyyyyyyyyy  bytes free
allmail
  • 133
  • 5

3 Answers3

2

The problem lies deeper than Perl. I wrote the following C code to compare:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char **argv) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s NAME\n", argv[0]);
        return EXIT_FAILURE;
    }

    const char *name = argv[1];
    struct stat st;
    if (stat(name, &st) == 0) {
        printf("stat(%s): success\n", name);
        switch (st.st_mode & S_IFMT) {
            case S_IFBLK:  printf("block device\n");            break;
            case S_IFCHR:  printf("character device\n");        break;
            case S_IFDIR:  printf("directory\n");               break;
            case S_IFIFO:  printf("FIFO/pipe\n");               break;
            case S_IFREG:  printf("regular file\n");            break;
            default:       printf("unknown?\n");                break;
        }
        return EXIT_SUCCESS;
    }
    printf("stat(%s): error: %s\n", name, strerror(errno));
    return EXIT_FAILURE;
}

(Perl's -d operator is just sugar around a stat call.)

I compiled it using the (MinGW) gcc that comes with Strawberry Perl:

gcc -Wall -Wextra -pedantic prog.c -o prog

It gives the same results:

C:\***>.\prog "C:\temp<>"
stat(C:\temp<>): success
directory

Thinking that it might be a quirk with the MinGW libraries, I tried the built-in dir command:

dir "C:\temp<>"

Curiously it doesn't fail, but it lists C:\ (not C:\temp<>) and shows only the Temp entry, not the rest of C:\.

I'm not sure what's going on here.

melpomene
  • 84,125
  • 8
  • 85
  • 148
  • Thank you for digging into this.Taking a clue from you, I tried this, please see my updated question – allmail Sep 16 '19 at 04:39
0

try this

if (-d $logsDir) {
    print "$logsDir exists";
} else {
    print "$logsDir does not exist!";
}
  • 1
    Much better. I always write the code in a `positive tone`. It means I check for the success instead of for the failure, whenever it is possible, of course. – Miroslav Popov Sep 12 '19 at 04:56
  • 1
    thanks for the answer but it still says the folder exists – allmail Sep 12 '19 at 20:28
  • I think this is to do with the file system/perl, it's most likely ignoring the special characters or stripping them off. Try it with a directory that you know 100% does not exist. – Taylor Goodall AU Sep 12 '19 at 23:53
  • -d works fine if lets say c:\tempAB did not exist. But my use case is that I want to catch c:\temp<> as invalid even if c:\temp exists. Wondering if this is a bug in perl (on windows)? – allmail Sep 13 '19 at 01:47
0

In windows, if you try to rename(or add) a folder with '<' or '>' character you will get error -

A filename cannot contain any of the following characters: \ / : * ? " < > |

So a file or folder is not supposed to contain these characters. I tried to do multiple runs on my machine similar the program mentioned by you-

1. .\directoryexist.pl c:\Perl64              <--    Exist
2. .\directoryexist.pl c:\Perl64<>            <--    Exist
3. .\directoryexist.pl c:\Perl64^<>^          <--    Exist

Now the same thing with double quotes-

4. .\directoryexist.pl "c:\Perl64"            <--    Exist
4. .\directoryexist.pl "c:\Perl64<>"          <--    Exist
5. .\directoryexist.pl "c:\Perl64^<^>"        <--    Not Exist

Now I looked at the answer here - How can I add greater than and less than into a batch file variable which contains the great explanation of this behavior.

Basically the gist is-

Adding '^' before '<' sets the value of "c:\Perl64^<^>" to "c:\Perl64<>" without any affect. When we used double quotes around our input it is taken as it is conataing '^' hence giving the output 'not exist'.

Now, As I mentioned before you cannot have certain character in names. So, when you are checking the existence of "c:\Perk64<>" it is converted to (I hope, but right now I do not have any proof for support) "c:\Perl64" which exist.

rai-gaurav
  • 536
  • 1
  • 8
  • 19
  • thanks, the real question is who/what is converting it? and why? Must be related to that these are not valid characters for a folder name – allmail Sep 16 '19 at 04:36