'How do I open a file only if it already exists?
This is what I am trying to achieve:
open(my $file,">>","/var/opt/input.txt");
if("/var/opt/input.txt" is opened sucessfully)
{
do some tasks;
}
else
{
do some other task;
}
Solution 1:[1]
So you want to open a file for appending but only if it already exists (so not create it).
One way is indeed to first check whether the file (doesn't) exist and then open it. However, then there is a race condition since the file can be created right after it's been checked! A rare thing to happen, mostly, but having a race condition is no good and always has to be avoided as it can lead to quiet and mysterious bugs.
This requirement is a good example of what sysopen
is for, when one needs more detailed control and flexibility. To directly do exactly what is needed
use Fcntl qw(O_WRONLY O_APPEND); # to bring in symbolic constants
if ( sysopen(my $fh, $filename, O_WRONLY | O_APPEND) ) { # fails if no file
say $fh scalar localtime; # appends to file
}
elsif ($!{ENOENT}) {
# The case to avoid, file doesn't exist ($!: "No such file or directory")
warn "Can't sysopen $filename: $!";
}
else {
# Some other error
warn "Can't sysopen $filename: $!";
}
With the given combination of flags the open call fails if the file doesn't already exist. Any file-open may fail in other ways as well so I separate the check for the absence of the file as the reason for failure (using %! hash). If that's excessive for your need just use one else
and print $!
from it .
If this is in a module remember to use carp
for a warning instead (need use Carp;
for that)
See sysopen and its section in perlopentut, as well as the useful Fcntl
Solution 2:[2]
As others have pointed out open()
returns a true or false value which indicates whether the file was opened successfully. However, it's a standard file-handling feature that if you try to open a file for writing (or appending) that doesn't already exist, then the file is created for you. And it sounds like that isn't what you want.
So you need to check whether the file exists before you try to open it. Perl has a number of file test operators that help you with that. You can use -f
which checks that a file exists.
my $file_name = '/var/opt/input.txt';
if (-f $file_name and open my $file, '>>', $file) {
# File exists and was opened successfully
} else {
# Either file doesn't exist or file can't be opened
}
You could also split it into two separate tests.
my $file_name = '/var/opt/input.txt';
if (-f $file_name) {
if (open my $file, '>>', $file) {
# File exists and was opened successfully
} else {
# File exists but can't be opened
}
} else {
# File doesn't exist
}
Solution 3:[3]
Note: This answers the original question "How to check if open() subroutine call gave a successful result in the Perl". The question was modified several times after I posted this answer.
From the documentation for open:
Open returns nonzero on success, the undefined value otherwise.
One way is to directly use open
in the if
clause:
if (open(my $file, ">>", "input.txt"))
{
#do some tasks;
}
else
{
#do some other task;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Dave Cross |
Solution 3 |