Bug #13889
closedFileUtils.rmdir が Errno::ENOTEMPTY を無視している
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) about 7 years ago
1.9から故意に無視するようになったようでしたので日本語リファレンスの方を修正しました。そのうちWebの方も反映されるかと思います。
Updated by sho-h (Sho Hashimoto) about 7 years ago
追記漏れに気付いたので追記しました。
Errno::ENOTEMPTYについてはoptions[:verbose]がtrueの時だけ何か出力するくらいはしてもいいかもしれません。
Updated by tkubo_ncs (Takehiro KUBO) about 7 years ago
1.9から故意に無視するようになった
ちなみにこちらは何か理由があったのでしょうか?
Errno::ENOTEMPTYについてはoptions[:verbose]がtrueの時だけ何か出力するくらいはしてもいいかもしれません。
はい、そのような挙動ならエラーに削除エラーに気づけて良いかと思います。
Updated by nobu (Nobuyoshi Nakada) about 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) about 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) almost 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) about 6 years ago
Seems related to https://bugs.ruby-lang.org/issues/3178 - maybe close that ticket?