Mac 应用程序如何跟踪文件的位置?

Mac 应用程序如何跟踪文件的位置?

我在 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

https://stackoverflow.com/questions/11951328/is-there-any-function-to-retrieve-the-path-linked-with-an-inode了解更多信息。

答案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

免责声明:我没有修剪“包含”列表,它很快就被拼凑在一起以证明这一点。

相关内容