Brian Candler
6/4/2007 2:09:00 PM
On Mon, Jun 04, 2007 at 10:14:49PM +0900, Ronald Fischer wrote:
> In my application, I often have blocks of code, where during preparation
> code, I need to make sure that certain files do not exist (in practice,
> this might be files left over from a previous run, which I didn't want
> to have erased earlier). Basically, I am doing something like this:
>
> if File.exist?(filename)
> File.unlink(filename)
> end
>
> or, equivalently,
>
> begin
> File.unlink(filename)
> rescue
> # ignore errors - it's OK if the file does not exist
> end
>
> This is necessary, because File::unlink signals non-existence of the
> file
> using an exception, instead by return code (as, for example, Perl's
> unlink
> does). The resulting code looks clumsy, because one always has to take
> care
> of an exception, which does not really signal an error condition (in
> Perl,
> I would simply ignore the return code of unlink).
There's
File.unlink(filename) rescue nil
However this catches everything under StandardError (I think), including
NoMethodError. So if you type
File.unlikn(filename) rescue nil
then you won't see the typo.
> Of course I could write my own unlink function like this:
>
> def silent_unlink(f)
> File.unlink(f) if File.exist?(f)
> end
> ...
> silent_unlink(filename)
FYI, that code has a "race" - the existence of a file may change between the
test and the unlink. So this code *may* raise an exception, very
occasionally.
You may think this isn't a realistic problem, but race conditions which
cause crashes once in a blue moon are extremely hard to pin down. So it's a
good aim to try and write code without races if at all possible.
It's also more efficient to try to remove the file, rather than to test for
its existence (stat) *and* then try to remove it afterwards.
Regards,
Brian.