From: johan556@... Date: 2007-05-16T10:03:42+09:00 Subject: FileUtils.rm_rf misfeature? Hi! The methods in "fileutils" seem to be modeled after UNIX commands like rm/mkdir/cd/... and sometimes with options added to the name (e.g. "mkdir_p"). I guess this also means that the methods should work like the corresponding UNIX commands. But I think "rm_rf" behaves strange. The corresponding UNIX command "rm -rf" has as a post condition that the files/directories given as argument should be *nonexisting* after the command. Otherwise the exit code will signal that the command failed. More specifically the man-page says the following about the -f option (on OS-X): -f Attempt to remove the files without prompting for confirma- tion, regardless of the file's permissions. If the file does not exist, do not display a diagnostic message or modify the exit status to reflect an error. The -f option overrides any previous -i options. It does *not* say that the command totally ignores any errors. To illustrate this, suppose I run the following commands: $ mkdir -p test-dir1/dir2 $ touch test-dir1/dir2/file1 $ sudo chown nobody:nobody test-dir1/dir2 $ rm -rf test-dir1 ; echo $status rm: cannot remove `test-dir1/dir2/file1': Permission denied 1 The exit is nonzero since the command failed to remove the directory tree. I suppose this means that FileUtils.rm_rf should give an exception in the same situation. But it doesn't. Should this be considered a bug in FileUtils, or is there some reason why FileUtils differ in behavior? Below I give a Ruby unit-test that illustrates the current "misfeature". /Johan Holmberg #-------------------------------- # NOTE: script uses "sudo" and "rm -rf". I don't like putting such "strong" # commands in test scripts, but used with caution it should not be dangerous. # And this unit test is just for illustrating the "bug". require "test/unit" require "fileutils" class TC_rm_rf < Test::Unit::TestCase def test_failing_rm_rf # setup tree that we will not be able to remove ok = true ok &&= system "sudo rm -rf test-dir1" ok &&= system "mkdir -p test-dir1/dir2" ok &&= system "touch test-dir1/dir2/file1" ok &&= system "sudo chown nobody:nobody test-dir1/dir2" assert(ok) begin FileUtils.rm_rf("test-dir1") got_exception = false rescue => e got_exception = true end if got_exception assert( File.exist?("test-dir1"), "Exception so we should have failed to remove 'test-dir1'" ) else assert( ! File.exist?("test-dir1"), "'test-dir1' still exists, but we got no exception" ) end end end #-------------------------------- Running the script above give the following error: 1) Failure: test_failing_rm_rf(TC_rm_rf) [TC_rm_rf.rb:28]: 'test-dir1' still exists, but we got no exception. is not true. 1 tests, 2 assertions, 1 failures, 0 errors #--------------------------------