はじめに
RubyのFile.deleteメソッドを使うときのちょっとしたテクニックを紹介します。
環境
Ruby2.6
内容
File.deleteはファイルを削除するメソッドです。データベースから読み込んだ内容をテキストファイルに書き込みをするような場合、同じ名前のファイルが既にあれば、このメソッドを利用して事前に削除します。
このメソッドをそのまま実行すると、つぎのような場合にエラーが発生することになります。
削除対象のファイルがないとき
ないファイルに対して削除しようとするとエラーが発生します。そのようなファイルはありませんという内容のエラーです。
Rubyにはなぜか、VBにはあったエラーが発生した行の次の行から処理を再開させる、Resume Nextに該当するメソッドがありません。(これ便利だったんだけどな・・・)
例外に飛んだ後、エラーに該当するerrnoでキャッチして、そこでなんらかの処理をしなくてはいけないことになります。
Rubyには代わりに、エラーが発生した行に戻る、retryといったメソッドがあります。例外の中で何もせずにretryをすると無限ループに陥ることになります。例外で削除対象のファイルをオープン&クローズさせてから、retryすると削除してくれます。
No such file or directory
errno:2
ファイルが開かれているとき
削除対象のファイルがオープンされたままの状態で、削除するとエラーになります。ファイルが開かれた状態になっていますといったエラーです。強制削除させるようなオプションがあればいいのだが、残念ながらありません。
例外処理でエラーに該当するerrnoをキャッチして、オープン&クローズさせてから、retryすると削除処理が正常に流れてます。
Text file busy
errno:26
ちょっとしたテクニック
File.deleteするときは、エラーが発生した都度、例外で何らかの処置をするのではなく、始めから、削除対処のファイルをオープン&クローズさせてあげればこと足ります。
fil = File.open("hoge.txt","a")
fil.close
File.delete("hoge.txt")
オープン&クローズを付けるだけで、想定される例外エラーは発生しなくなります。それでも、想定外のエラーが発生したときのために、例外処理はつけておいたことに越したことはないでしょう。
《疑問・その1》削除対処のファイルが初めからオープンされていた状態で、再度オープンさせてもエラーにならないのか?
エラーになりません。Rubyではどうやら、ファイルをオープンさせるときに、全てのファイル番号に対して、全てクローズさせてくれる処理が内部的に施されているようです。(この機能VBにはなかった)
《疑問・その2》ないファイルをオープンさせてエラーにならないのか?
エラーになりません。ないファイルをオープンさせると、0KBの空ファイルが作成されるだけです。ないファイルを削除させる場合は、0KBの空ファイルを事前に作成してあげて、削除処理を流してあげればいいのです。削除対処のファイルがある場合は、そのままオープンしてクローズされるだけです。
FileUtils を使う (補足)
FileUtilsを使ってファイル削除をすることもできます。force: trueというオプションを使うと、削除対象のファイルが存在しない場合、エラーにならずスルーしてくれます。こちらを使った方が幾分シンプルにコーディングができます。ほとんどの方はこちらをひいきに使っていることでしょう。
FileUtils.rm(file, force: true)