in reply to Check if file exists

How is -e $file true when $image is the empty string '' or even undef?

-e (or any of the other filetest functions documented here) accepts either a filehandle or a directory handle as its argument. When $image is empty or undefined, the assignment my $file = "$dir/$image"; initialises $file to just $dir/, which -e accepts as a directory handle — and since that directory exists, -e returns true.

(Note that if warnings are enabled, the concatenation of a string with undef will result in a warning like this:

Use of uninitialized value $image in concatenation (.) or string at -e + line...

which is a useful indicator that something is wrong.)

Your suggested fix — checking that $image has a true value — looks good to me. Another possibility is to confirm that $file is not a directory:

if (!-d $image && -e $image) { print "Yes image exists\n"; } else { print "No image doesn't exist\n"; }

Hope that helps,

Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Replies are listed 'Best First'.
Re^2: Check if file exists
by afoken (Chancellor) on May 06, 2018 at 16:22 UTC
    ... accepts either a filehandle or a directory handle ...

    Except that in this case, it's either a file name or a directory name. To use a handle, one would use the first argument of a successful open or opendir:

    #!/usr/bin/perl use v5.12; use warnings; my $fn='/etc/passwd'; open my $handle,'<',$fn or die "opening $fn failed: $!"; if (-T $handle) { say "$fn looks like text"; } else { say "$fn does not look like text"; } close $handle;

    Of course, to use a handle instead of a name, you first have to open a file or a directory. That won't work if it does not exist, or worse, a previously non-existing file might be created. So using handles instead of names for the -e, -f, -d, and -l tests is very uncommon.


    A related problem, especially with the -e and -f tests is TOCTOU: You may get a race condition that may be a security problem. Your program is not the only software that runs on the computer. The operating system may switch to another program, practically at any time. So between -e/-f and a following open, things may change drastically in the filesystem, and your program decides on obsolete information. The best way to avoid this problem is to simply allow open to fail, and check $! in case open fails.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)