如何检测文件是不是可在 Ruby 中写入?

Posted

技术标签:

【中文标题】如何检测文件是不是可在 Ruby 中写入?【英文标题】:How can I detect whether a file is writeable in Ruby?如何检测文件是否可在 Ruby 中写入? 【发布时间】:2016-03-18 20:45:17 【问题描述】:

如果其中任何一个为真,则该函数应返回假:

    完整路径是现有目录。 路径不是合法的文件名(无效字符、太长等) 路径引用当前用户不可写的现有文件。 路径包括任何不存在的目录段。

如果所有这些都为真,该函数应该返回真:

    除文件名外的所有路径段都已存在目录。 该文件不存在或存在且可由当前用户写入。 保存文件的目录可由当前用户写入。 路径段和文件名不会太长,并且仅由文件名的有效字符组成。 指定了相对或绝对路径。

该函数必须在使用 Ruby 1.9.3 的 MAC OSX 上运行。

当文件不存在并且应该是可写的时,以下方法返回 false,即使我是从我自己的用户目录的子目录运行它:

File.writable?('./my-file-name')

我将接受涉及调用文件打开并在写入失败时捕获异常的解决方案,但我更喜欢不依赖异常。

这是我目前所拥有的,但它不能处理一些边缘情况:

  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

我仍然不知道如何方便地测试是否缺少任何目录段,或者名称中是否有奇怪的字符,以及其他一些情况。

【问题讨论】:

听起来您希望我们为您编写代码。这并不是 Stack Overflow 的真正用途。请花点时间阅读How To Ask。 @乔丹。并不真地。我是红宝石的新手。当我在标准库中找到一个名为“File.writable?”的函数时无法告诉我文件实际上是否可写,我假设我不了解 Ruby 文件 IO 库。由于测试文件是否可以编写是我使用过的许多其他语言的单行,我假设这个问题的答案是单行,只是像我这样的 Ruby 新手不知道的。如果有这样一条线,那几乎不是“请人为我写代码”。我花了一个小时在 Ruby 文档中寻找一个函数,结果空手而归。 Ruby 中没有一种方法可以满足您所有非常具体的标准。 File.writable? 适用于您在自己的测试中发现的现有文件(和目录)。有了这些知识,我怀疑你可以编写一个方法——或者至少尝试编写一个方法——它确实满足你所有非常具体的标准。一旦您进行了尝试并遇到了特定问题,Stack Overflow 是一个提问的好地方。 @乔丹。知道 Ruby 中没有一个函数可以满足我的需求,这非常有帮助,并且会阻止我再花几个小时寻找。谢谢。 Unix systems treat directories as a type of file. Ruby 是面向 Unix 的。 【参考方案1】:

Ruby 在其 std-lib 中包含 Pathname,它是其他几个面向文件的类的包装器:

File、FileTest 的所有功能以及 Dir 和 FileUtils 的一些功能都包含在内,这并不奇怪。它本质上是所有这些的门面,甚至更多。

“路径名”可以是目录或文件。

Pathname 并不能满足您的所有要求,但它是一个非常方便的起点。您可以轻松添加所需的附加功能,因为它是一个包装器,比您尝试使用单个类实现解决方案要容易得多。

当我必须进行大量目录/文件处理时,这是我的首选课程。

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

您无法判断目录中缺少哪些组件,但通常我们会尝试创建它并在异常发生时挽救异常,处理权限错误。编写代码来查找完整目录路径并不难,然后如果完整路径不存在,则遍历目录链,将每个目录作为前一个目录的子项查找。 Enumerable's findfind_all 会很有用。

【讨论】:

以上是关于如何检测文件是不是可在 Ruby 中写入?的主要内容,如果未能解决你的问题,请参考以下文章

检测 ruby​​ 是不是在 Windows 上运行的正确方法是啥?

如何检查目录是不是可在 PHP 中写入?

如何在 Linux 上使用 Ruby 实现实时 USB 存储检测?

如何检测到没有人在 Linux 中写入文件?

在 Ruby 中检测没有 getc/gets 的按键(非阻塞)

在 Ruby 中检测上传文件的 MIME 类型