Search code examples
perlmojolicious

"if (-f $file_path1) {" is always true regardless whether or not a file exists


In my Mojolicious app I have this:

if (-f $file_path1) {
    app->log->debug("file1 exists: $file_path1");
    # ...........

} else {
    app->log->debug("file1 doesn't exist: $file_path1; creating....\r\n");

Regardless of its presence, it never prints "file1 doesn't exist"

When I remove it, it still doesn't print that it doesn't exist.

How can this be?


Solution

  • First of all, to check if a file exists, you want -e or stat (not -f).

    Secondly, you treat "exists but isn't a plain file" results, "file not found" errors and other errors as "file not found" errors. If things aren't working as you expect, you should check more closely what is error is actually being returned!

    if (-e $file_path1) {
       app->log->debug("\"$file_path1\" already exists.\n");
    }
    elsif ($!{ENOENT}) {
       app->log->debug("\"$file_path1\" doesn't exist. Creating...\n");
    }
    else {
       app->log->debug("Error stating \"$file_path1\": $!\n");
    }
    

    or

    if (stat($file_path1)) {
       app->log->debug("\"$file_path1\" already exists.\n");
    }
    elsif ($!{ENOENT}) {
       app->log->debug("\"$file_path1\" doesn't exist. Creating...\n");
    }
    else {
       app->log->debug("Error stating \"$file_path1\": $!\n");
    }
    

    If you were using -f because you also wanted to check if it's a plain file, you can use the following:

    my $rv = -f $file_path1;
    if (defined($rv)) {
       if ($rv) {
          app->log->debug("\"$file_path1\" already exists.\n");
       } else {
          app->log->debug("\"$file_path1\" already exists, but isn't a plain file.\n");
       }
    } else {
       if ($!{ENOENT}) {
          app->log->debug("\"$file_path1\" doesn't exist. Creating...\n");
       } else {
          app->log->debug("Error stating \"$file_path1\": $!\n");
       }
    }
    

    or

    if (stat($file_path1)) {
       if (-f _) {
          app->log->debug("\"$file_path1\" already exists.\n");
       } else {
          app->log->debug("\"$file_path1\" already exists, but isn't a plain file.\n");
       }
    } else {
       if ($!{ENOENT}) {
          app->log->debug("\"$file_path1\" doesn't exist. Creating...\n");
       } else {
          app->log->debug("Error stating \"$file_path1\": $!\n");
       }
    }
    

    Assuming you're right and the problem isn't really that the file doesn't exist, any of these snippets will get the reason the file can't be stated. A permission problem, perhaps?

    If my snippets tell you that the file doesn't exist, then it really doesn't. Make sure the value you are passing to stat/-e/-f contains what you think it does (e.g. no trailing spaces, CR or LF). If the path is a relative path, it could also be that you are making incorrect assumptions about the current work directory.