|
|
 |
 |
 |
 |
Ruby Programming Language
|
 |
 |
 |
 |
 |
 |
 |
 |
Deleting a file - is there a less clumsy way to do this?
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). 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 already might have a non-exception-throwing unlink function built in somewhere? Ronald -- Ronald Fischer <ronald.fisc@venyon.com> Phone: +49-89-452133-162
Ronald Fischer wrote: > 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 -- Posted via http://www.ruby-forum.com/.
In message <387E9FC1619C0849BA8934938037E54F088@sv-muc-004.venyon-mail.local>, "Ronald Fisch er" writes: >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
These are not equivalent. There are other possible reasons for which an unlink attempt could fail! Consider what happens if two programs run through that first example at the same time. That said, I would love a non-exception-raising way to try an unlink. -s
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.
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
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
> > 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. :-)
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
> 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.
Interesting (didn't know about this variation), but, as you said, too risky, as typos would be ignored too. > > 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.
Thank you for pointing this out. You are very right. Ronald
On Jun 4, 9:26 am, "Ronald Fischer" <ronald.fisc@venyon.com> wrote:
> > > 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. :-) > 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
On Jun 4, 2007, at 12:15 PM, Daniel Berger wrote:
> On Jun 4, 9:26 am, "Ronald Fischer" <ronald.fisc @venyon.com> wrote: >>>> 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. :-) >> 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
so check success by checking File.exists? again...? Or find out if the file is in use and then wait?
On Jun 4, 11:42 am, John Joyce <dangerwillrobinsondan@gmail.com> wrote:
> On Jun 4, 2007, at 12:15 PM, Daniel Berger wrote: > > On Jun 4, 9:26 am, "Ronald Fischer" <ronald.fisc@venyon.com> wrote: > >>>> 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. :-) > >> 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 > so check success by checking File.exists? again...? > Or find out if the file is in use and then wait?- Hide quoted text - >
begin File.delete(file) rescue Errno::EACCES puts "There's an open handle somewhere" raise rescue Errno::ENOENT # Ignore end Regards, Dan
Jamey Cribbs wrote: > 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! -- Posted via http://www.ruby-forum.com/.
> > 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) ?
Thank you - this is indeed a useful solution! Ronald -- Ronald Fischer <ronald.fisc@venyon.com> Phone: +49-89-452133-162
> > In Perl for instance, I would simply write > > unlink filename; > > and implicitly void the result... > 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 File.delete 'xx' Went well. No ecxeption. File was deleted afterwards. Ronald -- Ronald Fischer <ronald.fisc@venyon.com> Phone: +49-89-452133-162
|
 |
 |
 |
 |
|