5

I noticed strange behavior of the -d flag to check if a file is a directory and if the directory exists. It behaves differently when using ~/my_dir as my path.

The following code will return false, even though the directory my_dir exists, but if I'll change it to a full path like /home/ricky/my_dir, then the if statement will return true.

#!/usr/bin/perl -w
#
use strict;

if ( -d "~/my_dir") {
    print "Found \n";
}
else {
    print "Not found \n";
}

What's the difference?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ricky Levi
  • 7,298
  • 1
  • 57
  • 65
  • See http://stackoverflow.com/questions/976968/why-does-my-perl-script-fail-on-but-works-with-envhome & http://stackoverflow.com/questions/4043785/how-can-i-make-perl-recognize-paths-with/ – devnull May 23 '13 at 16:19
  • Also try `ls "~/mydir"` - you'll figure the `difference`. – devnull May 23 '13 at 16:21
  • Thanks, those solutions uses other modules that I'm always trying to avoid, but I got the point :) – Ricky Levi May 23 '13 at 16:27

3 Answers3

12

~ is a shell shortcut to indicate the home directory, it is unknown to perl. You have to use the environment variable HOME here -- for instance using "$ENV{HOME}/my_dir".

fge
  • 119,121
  • 33
  • 254
  • 329
  • BTW, using system vs back-ticks makes ~/ work in the 'system' function, which is also a difference that I just found ... ( also symlinks have the same issue ) - thanks for the answer :) – Ricky Levi May 23 '13 at 16:28
  • Unknown to the *system*, even. Perl doesn't do anything with the path but pass it to the system. – ikegami May 23 '13 at 16:32
  • @Ricky That's because the `system` function runs a `/bin/sh`, which will do its shell substitutions on your command line. – aschepler Aug 21 '14 at 18:52
  • @aschepler I just run system('echo $SHELL'); and it says /bin/bash .. so I'm not sure this is correct. – Ricky Levi Aug 23 '14 at 13:49
  • That's just the environment variable. Try `system(q(ps $$))`. – aschepler Aug 23 '14 at 16:26
  • @aschepler I'm not sure what I'm suppose to see ... this is the output 17507 pts/0 R+ 0:00 ps 17507 – Ricky Levi Aug 27 '14 at 05:56
5

~ is not a real path. Shells such as /bin/bash expand it to the value of the $HOME environment variable. Perl does not. So, you should use something like this instead:

if ( -d "$ENV{HOME}/my_dir" ) {
    ...
}
We Are All Monica
  • 13,000
  • 8
  • 46
  • 72
-2

You can check by executing the chdir command also. chdir "dir_name" will return 0, if directory is not present. And 1 if directory is present.

Dheeraj Arya
  • 71
  • 1
  • 6
  • 1
    `-d` is the correct way to tell whether a directory exists. `chdir` has the side effect of changing to the directory; it will also fail if `dir_name` is a directory but you don't have permission to change to it. And this doesn't address the OP's problem, which is the use of `~`. – Keith Thompson May 28 '15 at 23:08