Project

General

Profile

Actions

Bug #13889

closed

FileUtils.rmdir が Errno::ENOTEMPTY を無視している

Added by tkubo_ncs (Takehiro KUBO) over 7 years ago. Updated over 6 years ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 2.1.6p336 (2015-04-13 revision 50298)
[ruby-dev:50236]

Description

2.1 や最新のリファレンスには FileUtils.rmdir で削除対象のディレクトリが空ではない場合は Errno::ENOTEMPTY が発生すると書かれていますが、
FileUtils.rmdir を空でないディレクトリに対して呼んでもエラーにはならず、削除もされません。

irb(main):002:0> FileUtils.mkdir("dir")
=> ["dir"]
irb(main):003:0> FileUtils.touch("dir/file")
=> ["dir/file"]
irb(main):004:0> FileUtils.rmdir("dir")
=> ["dir"]                                   #<= エラーは出ない
irb(main):005:0> File.exist?("dir")          #<= 残っている
=> true
irb(main):006:0> File.exist?("dir/file")
=> true

fileutils.rb のソースで ENOTEMPTY が rescue されているようです。(trunk でも)

def rmdir(list, options = {})
  fu_check_options options, OPT_TABLE['rmdir']
  list = fu_list(list)
  parents = options[:parents]
  fu_output_message "rmdir #{parents ? '-p ' : ''}#{list.join ' '}" if options[:verbose]
  return if options[:noop]
  list.each do |dir|
    begin
      Dir.rmdir(dir = remove_tailing_slash(dir))
      if parents
        until (parent = File.dirname(dir)) == '.' or parent == dir
          dir = parent
          Dir.rmdir(dir)
        end
      end
    rescue Errno::ENOTEMPTY, Errno::EEXIST, Errno::ENOENT    <= ここです
    end
  end
end
module_function :rmdir

実際無視するのが正しいならリファレンスの方を修正していただければと思います。

Updated by sho-h (Sho Hashimoto) over 7 years ago

1.9から故意に無視するようになったようでしたので日本語リファレンスの方を修正しました。そのうちWebの方も反映されるかと思います。

Updated by sho-h (Sho Hashimoto) over 7 years ago

追記漏れに気付いたので追記しました。

Errno::ENOTEMPTYについてはoptions[:verbose]がtrueの時だけ何か出力するくらいはしてもいいかもしれません。

Updated by tkubo_ncs (Takehiro KUBO) over 7 years ago

1.9から故意に無視するようになった

ちなみにこちらは何か理由があったのでしょうか?

Errno::ENOTEMPTYについてはoptions[:verbose]がtrueの時だけ何か出力するくらいはしてもいいかもしれません。

はい、そのような挙動ならエラーに削除エラーに気づけて良いかと思います。

Actions #4

Updated by nobu (Nobuyoshi Nakada) over 7 years ago

  • Status changed from Open to Closed

Applied in changeset trunk|r59934.


fileutils.rb: error at rmdir

  • lib/fileutils.rb (rmdir): should not ignore errors first, except
    for parent directories. [ruby-dev:50236] [Bug #13889]

Updated by nagachika (Tomoyuki Chikanaga) over 7 years ago

  • Status changed from Closed to Open

r59934 の変更で parent で親ディレクトリに遡っている時以外は Errno::ENOTEMPTY を無視しないように変更したようです(従ってドキュメントの ENOTEMPTY の記述の削除は戻したほうがいいかも?)。しかし存在しない名前を FileUtils.rmdir に指定した時にエラーにならなかったのが Errno::ENOENT が発生するなるようになってしまっているようです。

% ./ruby -r fileutils -e 'FileUtils.rmdir "notexist"'
% ./ruby -r ./lib/fileutils -e 'FileUtils.rmdir "notexist" rescue p $!'
#<Errno::ENOENT: No such file or directory @ dir_s_rmdir - notexist>

Updated by nagachika (Tomoyuki Chikanaga) about 7 years ago

  • Status changed from Open to Closed
  • Backport changed from 2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: UNKNOWN to 2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: DONTNEED

「しかし存在しない名前を FileUtils.rmdir に指定した時にエラーにならなかったのが Errno::ENOENT が発生するなるようになってしまっている」 については、fileutils はコマンドラインツールの挙動に倣うもので、rmdir(1) が存在しないパスを指定された時にはエラーになるので、r59934 後の挙動のほうが正しいということで閉じてしまいます。

一応挙動が変わるので、Backport 欄は 2.4 は DONTNEED にしておきます。

Updated by vo.x (Vit Ondruch) almost 7 years ago

The decision to not backport this is questionable IMO.

For example, the test suite of spring-watcher-listen passes testing against Ruby 2.4, but unintentionally leaves files/directories behind, because the FileUtils.rmdir secretly swallows the errors.

Testing against Ruby 2.5, the test suite fails of course and at the end, the code must be fixed anyway 1.

So why not backport this? Why are you keep hiding something which is obviously error?

Updated by apeiros (Stefan Rusterholz) over 6 years ago

Seems related to https://bugs.ruby-lang.org/issues/3178 - maybe close that ticket?

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0