How can I detect whether a file is writeable in Ruby?
The function should return false if any of these are true:
The function should return true if all of these are true:
The function must work on MAC OSX using Ruby 1.9.3.
The following method returns false when the file does not already exist and should be writable, even though I am running it from a subdirectory of my own user directory:
File.writable?('./my-file-name')
I will accept a solution involving calling file open and catching the exception if a write fails, though I prefer to not rely on exceptions.
Here is what I have so far, but it does not handle some edge cases:
def file_writable?(filename)
return false if (filename || '').size == 0
return false if File.directory?(filename)
return false if File.exists?(filename) && !File.writable(filename)
return true;
end
I still do not know how to conveniently test if any directory segments are missing, or if weird characters are in the name, and some other cases.
Ruby includes Pathname in its std-lib, which is a wrapper around several other file-oriented classes:
All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
A "pathname" can be a directory or a file.
Pathname doesn't do all the things you require, however it acts as a very convenient starting point. You can easily add the additional functionality you need since it is a wrapper, much easier than if you tried to implement a solution using the individual classes.
It's my go-to class when I have to do a lot of directory/file processing.
require 'pathname' # => true
foo = Pathname.new('/usr/bin/ruby') # => #<Pathname:/usr/bin/ruby>
foo.writable? # => false
foo.directory? # => false
foo.exist? # => true
tmp = Pathname.new('/tmp/foo') # => #<Pathname:/tmp/foo>
tmp.write('bar') # => 3
tmp.writable? # => true
tmp.directory? # => false
tmp.exist? # => true
bin = Pathname.new('/usr/bin') # => #<Pathname:/usr/bin>
bin.writable? # => false
bin.directory? # => true
bin.exist? # => true
fake = Pathname.new('/foo/bar') # => #<Pathname:/foo/bar>
fake.exist? # => false
You can't tell what components are missing from a directory, but normally we'd try to create it and rescue the exception if it occurs, dealing with permission errors. It wouldn't be hard to write code to look for a full directory path, then iterate though the chain of directories if the full-path doesn't exist, looking for each as a child of the previous one. Enumerable's find
and find_all
would be useful.
上一篇: 编写我自己的3D游戏引擎
下一篇: 如何检测文件是否可以在Ruby中写入?