如何从ruby中的IO对象获取文件名

时间:2011-10-25 10:34:43

标签: ruby io

红宝石......

我有一个由外部进程创建的IO对象,我需要从中获取文件名。 但是我似乎只能得到文件描述符(3),这对我来说并不是很有用。

有没有办法从这个对象获取文件名甚至获取文件对象?

我从通知程序获取IO对象。那么这也可能是获取文件路径的一种方式吗?

2 个答案:

答案 0 :(得分:6)

how to get a the filename in C上有一个类似的问题,我将以红宝石的方式提出这个问题的答案。

在Linux中获取文件名

假设io是您的IO对象。以下代码为您提供文件名。

File.readlink("/proc/self/fd/#{io.fileno}")

例如,如果在为其创建io对象后删除了文件,则不起作用。使用此解决方案,您可以使用文件名,但不能使用File对象。

获取不知道文件名

的File对象

方法IO#for_fd可以创建IO,它是任何给定整数filedescriptor的子类。通过执行以下操作获取fd的File对象:

File.for_fd(io.fileno)

不幸的是,这个File对象不知道文件名。

File.for_fd(io.fileno).path # => nil

我浏览了ruby-1.9.2来源。在创建文件对象之后,纯ruby中似乎无法操纵路径。

获取知道文件名

的File对象

可以在C中创建对ruby的扩展,首先调用File#for_fd,然后操作Files内部数据结构。这个源代码适用于ruby-1.9.2,对于其他版本的ruby,它可能必须被调整。

#include "ruby.h"
#include "ruby/io.h"

VALUE file_fd_filename(VALUE self, VALUE fd, VALUE filename) {
    VALUE file= rb_funcall3(self, rb_intern("for_fd"), 1, &fd);
    rb_io_t *fptr= RFILE(rb_io_taint_check(file))->fptr;
    fptr->pathv= rb_str_dup(filename);
    return file;
}

void Init_filename() {

    rb_define_singleton_method(rb_cFile, "for_fd_with_filename", file_fd_filename, 2);

}

现在你可以在编译之后做到:

require "./filename"
f= File.for_fd_with_filename(io.fileno, File.readlink("/proc/self/fd/#{io.fileno}"))
f.path # => the filename

readlink也可以放入File#for_fd_with_filename定义。这个例子只是为了说明它是如何工作的。

答案 1 :(得分:0)

如果您确定IO对象代表文件,您可以尝试这样的

path = io.path if io.respond_to?(:path)

See documentation for File#path