我在 Mac 上观察到如下行为:
- 使用 PDF Expert 打开 PDF,对文件进行一些更改,在 Finder 中移动文件,将其保存在 PDF Expert 中,它将正确保存到新位置。
- 在类似 的目录中打开 shell
~/foo
,使用另一个应用程序对该目录进行垃圾处理,并且 shell 的 pwd 正确输出~/.Trash/foo
。
幕后发生了什么?这些情况似乎表明应用程序不仅仅像 emacs 那样保存文件的绝对路径(我的说法正确吗?),或者它是一种完全不同的机制?
答案1
macos 有一个/.vol/
映射到实际目录和文件的特殊系统。/.vol/<device_id>/<inode_number>
无论文件位于文件系统的哪个位置,都可以通过 访问文件和目录。
这是一个很好的小系统。
因此,程序可以获取 的 inode 编号/Users/jdoe/someFile.txt
,然后通过/.vol/12345/6789
(在本例中,设备 id 为 12345,inode 编号为 6789)打开它。然后,您可以移动到/Users/jdoe/someFile.txt
任何您想要的位置(在同一卷上),一切都会正常工作。您甚至可以编写支持此功能的 shell 脚本magic
。
ls -di <file>
获取索引节点号。
$ ls -di /User/jdoe/someFile.txt
6789 /User/jdoe/someFile.txt
编辑:
您可以stat
根据 IMSoP 突出显示的链接答案来获取卷的 id 和索引节点号。
GetFileInfo /.vol/12345/6789
将返回先前位于 中的文件的当前位置/Users/jdoe/someFile.txt
。
答案2
下面的答案是错误的(见评论)。请忽略
除了 thecarpy 给出的好答案之外,您的程序很可能只是保存一个文件处理,它独立于目录树中的文件位置(并且在 Unix 系统上甚至会持续删除文件,至少在您关闭它之前)。
文件句柄基本上是对文件的直接访问,与文件在目录结构中的位置或频率(在硬链接的情况下)无关。
答案3
虽然我不确定为什么 macos 使用这个而不是标准的 C 功能,但假设我几年前在“Mac OS X Unleashed”中读到的内容是正确的,事实证明我再次学到了一些新东西。
请看下面的简单C程序:
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
struct timespec ts;
ts.tv_sec = 10;
ts.tv_nsec = 0;
FILE * fp;
fp = fopen("file.txt", "a");
int f = fileno(fp);
if (fp == NULL)
{
printf("Error opening file!\n");
exit(1);
}
struct stat file_stat;
int ret;
ret = fstat (f, &file_stat);
printf("inode number is %d\n", file_stat.st_ino);
nanosleep(&ts, NULL);
printf("Finished sleep, writing to file.\n");
/* print some text */
const char *text = "Write this to the file";
dprintf(f, "Some text: %s\n", text);
/* print integers and floats */
int i = 1;
float py = 3.1415927;
dprintf(f, "Integer: %d, float: %f\n", i, py);
/* printing single characters */
char c = 'A';
dprintf(f, "A character: %c\n", c);
close(f);
}
编译程序,在后台快速运行它,mv file.txt file2.txt
然后程序打印“完成睡眠,写入文件”。 (你有10秒的时间)
请注意,它file2.txt
具有程序的输出,尽管它在文本打印到文件之前已被移动(通过文件描述符)。
$ gcc myfile.c
$ ./a.out &
[1] 21416
$ inode number is 83956
$ ./mv file.txt file2.txt
$ Finished sleep, writing to file.
[1]+ Done ./a.out
$ cat file2.txt
Some text: Write this to the file
Integer: 1, float: 3.141593
A character: A
免责声明:我没有修剪“包含”列表,它很快就被拼凑在一起以证明这一点。