打印 FILE* 对应文件的路径。

6
FILE * fd = fopen ("/tmp/12345","wb");

如果我有变量 fd,如何在 Linux 环境中打印文件路径(/tmp/12345)?

请注意,D.Nathanael 对于 macOS 的答案没有在其他答案中表示(尽管我现在已经在三个问题的每个评论中指向它)。 - Jonathan Leffler
3个回答

7

你不能只用标准C语言来实现。

在Linux上,您可以执行以下操作:

#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include <stdlib.h>


int print_filename(FILE *f)
{
    char buf[PATH_MAX];
    char fnmbuf[sizeof "/prof/self/fd/0123456789"];
    sprintf(fnmbuf,"/proc/self/fd/%d", fileno(f));
    ssize_t nr;
    if(0>(nr=readlink(fnmbuf, buf, sizeof(buf)))) return -1;
    else buf[nr]='\0';
    return puts(buf);
}

int main(void)
{
    FILE * f = fopen ("/tmp/12345","wb");
    if (0==f) return EXIT_FAILURE;
    print_filename(f);

}

3
注意:readlink()函数不会在字符串末尾添加空字符。你需要捕获它返回的值(即包含名称的字节数组的长度),然后在将其作为字符串传递给puts()之前,添加空字符。 - Jonathan Leffler

6

由于 MacOS 没有 /proc 目录,使用 fcntl 是获取文件描述符路径的一个好选择!

下面是一个可用的示例:

#include <sys/syslimits.h>
#include <fcntl.h>

char filePath[PATH_MAX];
if (fcntl(fd, F_GETPATH, filePath) != -1)
{
    printf("%s", filePath);
}

但它仅适用于MacOS,对于Linux,Pskocik的解决方案使用readlink似乎是最佳答案。


2
有趣!虽然不符合POSIX标准(fcntl())。 - Jonathan Leffler
很好的解决方案适用于MacOS。但是它在Linux上不起作用。至少我的Linux glibc中没有一个fcntl.h定义F_GETPATH。 - Petr Skocik
哦,是啊,我很惊讶!看起来已经有一个补丁了,但没有实施:https://lwn.net/Articles/277736/ -- 我会编辑我的答案,给出一个Linux的答案和macOS的答案。 - Nathanael Demacon
这也适用于FreeBSD(实际上是所有*BSD),其中procfs默认未启用。 - rustyx

5

没有标准方法从FILE *对象中检索路径名,主要是因为您可能会有未与命名文件相关联的流(stdinstdoutstderr、管道等)。各平台可以提供从流中获取路径的实用程序,但您需要查阅该平台的文档。

否则,您需要手动跟踪该信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接