Deleting a file - is there a less clumsy way to do this?

R

Ronald Fischer

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=20
# ignore errors - it's OK if the file does not exist
end=20

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).

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)

but I am wondering whether this is not a such common problem, that Ruby=20
already might have a non-exception-throwing unlink function built in
somewhere?

Ronald
--=20
Ronald Fischer <[email protected]>
Phone: +49-89-452133-162
=20
 
D

Daniel Lucraft

Ronald said:
but I am wondering whether this is not a such common problem, that Ruby
already might have a non-exception-throwing unlink function built in
somewhere?

Ronald

FileUtils.rm_f(filename) ?

best,
Dan
 
B

Brian Candler

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.
 
J

Jamey Cribbs

Ronald said:
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

You can get it down to one line by doing this:

File.delete(filename) if File.exist?(filename)


That doesn't look so bad. :)


Jamey
 
R

Ronald Fischer

Basically, I am doing something like this:
=20
You can get it down to one line by doing this:
=20
File.delete(filename) if File.exist?(filename)
=20
=20
That doesn't look so bad. :)

Well, I'm not so much concerned about the *lines* of code,
but of the complexity, in particular since this variation
requires to name "filename" twice.

(side note: why does this remind me to the ongoing thread
"Introducing the "it" keyword"..... ;-)

In Perl for instance, I would simply write=20

unlink filename;

and implicitly void the result...


Ronald
 
R

Ronald Fischer

File.unlink(filename) rescue nil
=20
However this catches everything under StandardError (I=20
think), including
NoMethodError. So if you type
=20
File.unlikn(filename) rescue nil
=20
then you won't see the typo.

Interesting (didn't know about this variation), but, as you said,=20
too risky, as typos would be ignored too.
=20
FYI, that code has a "race" - the existence of a file may=20
change between the
test and the unlink. So this code *may* raise an exception, very
occasionally.

Thank you for pointing this out. You are very right.

Ronald
 
D

Daniel Berger

Well, I'm not so much concerned about the *lines* of code,
but of the complexity, in particular since this variation
requires to name "filename" twice.

(side note: why does this remind me to the ongoing thread
"Introducing the "it" keyword"..... ;-)

In Perl for instance, I would simply write

unlink filename;

and implicitly void the result...

Ronald

Note that this approach would silently fail on MS Windows if another
process had an open handle on the file in question, i.e. the file
_does_ exist, but you did not delete it.

Regards,

Dan
 
J

John Joyce

Note that this approach would silently fail on MS Windows if another
process had an open handle on the file in question, i.e. the file
_does_ exist, but you did not delete it.

Regards,

Dan
so check success by checking File.exists? again...?
Or find out if the file is in use and then wait?
 
D

Daniel Berger

so check success by checking File.exists? again...?
Or find out if the file is in use and then wait?- Hide quoted text -

- Show quoted text -

begin
File.delete(file)
rescue Errno::EACCES
puts "There's an open handle somewhere"
raise
rescue Errno::ENOENT
# Ignore
end

Regards,

Dan
 
L

Lloyd Linklater

Jamey said:
You can get it down to one line by doing this:

File.delete(filename) if File.exist?(filename)


That doesn't look so bad. :)

Very nice, Jamey!
 
R

Ronald Fischer

In Perl for instance, I would simply write
=20
Note that this approach would silently fail on MS Windows if another
process had an open handle on the file in question, i.e. the file
_does_ exist, but you did not delete it.

Does it really? I tried the following:

(1) Created a file xx
(2) From a cygwin bash shell, made a tail -f on the file.
(3) Started an editor (Scite) on that file. Made some changes to the
file. Saved them. Made more changes in the editor.

Now there should be two open handles on the file: At least the tail -f,
and very likely also from Scite (though this depends on how Scite is
implemented).

Now, from irb, I did a=20

File.delete 'xx'

Went well. No ecxeption. File was deleted afterwards.

Ronald
--=20
Ronald Fischer <[email protected]>
Phone: +49-89-452133-162
=20
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,235
Members
46,821
Latest member
AleidaSchi

Latest Threads

Top