如何在 Rust 中获取打开的 std::fs::File 的文件名?

And*_*ers 5 linux file rust

我有一个 open std::fs::File,我想获取它的文件名,例如作为PathBuf. 我怎么做?

简单的解决方案是只保存调用中使用的路径File::open。不幸的是,这对我不起作用。我正在尝试编写一个读取日志文件的程序,并且写入日志的程序不断更改文件名,作为其日志轮换的一部分。因此,该文件很可能在打开后已被重命名。这是在 Linux 上,因此可以重命名打开的文件。

如何解决此问题并获取打开文件的当前文件名?

Sve*_*ach 6

在典型的 Unix 文件系统上,一个文件可能同时有多个文件名,甚至根本没有。文件元数据存储在一个inode 中,该inode具有唯一的inode 编号,并且该 inode 编号可以与任意数量的目录条目链接。但是,没有从 inode 返回到目录条目的反向链接。

给定一个FileRust 中的开放对象,您可以使用ino()方法获取 inode 编号。如果您知道日志文件所在的目录,您可以使用std::fs::read_dir()该目录中的所有条目进行迭代,并且每个条目也将有一个ino()方法,因此您可以找到与您打开的文件对象匹配的条目。当然,这种方法会受到竞争条件的影响——一旦你尝试用它做任何事情,目录条目可能已经消失了。


myr*_*cat 5

在 Linux 上,当前进程持有的文件句柄可以在 下找到/proc/self/fd。这些看起来和行为就像原始文件的符号链接(尽管我认为它们在技术上可能是其他东西 - 也许了解更多的人可以参与进来)。

/proc/self/fd因此,您可以通过使用文件描述符构造正确的路径来恢复(可能已更改的)文件名,然后按照符号链接返回文件系统。

此代码片段显示了以下步骤:

use std::fs::read_link;
use std::os::unix::io::AsRawFd;
use std::path::PathBuf;

// if f is your std::fs::File

// first construct the path to the symlink under /proc
let path_in_proc = PathBuf::from(format!("/proc/self/fd/{}", f.as_raw_fd()));

// ...and follow it back to the original file
let new_file_name = read_link(path_in_proc).unwrap();
Run Code Online (Sandbox Code Playgroud)

  • Linux 在大多数情况下可以跟踪重命名,但也有限制。例如,如果您首先向文件添加新文件名(即硬链接),然后删除旧文件名,您将无法找到新名称。 (3认同)