135

我知道这不是应该做的事情,但是有没有办法使用通常在 Linux 中分隔文件名中的目录的斜线字符?

4

8 回答 8

145

答案是你不能,除非你的文件系统有错误。原因如下:

有一个系统调用用于重命名中定义的fs/namei.c文件renameat

SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
                int, newdfd, const char __user *, newname)

当系统调用被调用时,它会do_path_lookup在名称上进行路径查找 ( )。继续跟踪这个,我们得到link_path_walk这个:

static int link_path_walk(const char *name, struct nameidata *nd)
{
       struct path next;
       int err;
       unsigned int lookup_flags = nd->flags;

       while (*name=='/')
              name++;
       if (!*name)
              return 0;
...

此代码适用于任何文件系统。这是什么意思?这意味着,如果您尝试使用传统方式传递带有实际'/'字符的参数作为文件名,它将无法执行您想要的操作。没有办法逃脱角色。如果文件系统“支持”这一点,那是因为它们要么:

  • 使用 unicode 字符或看起来像斜线但不是的东西。
  • 他们有一个错误。

此外,如果您确实进入并编辑字节以将斜杠字符添加到文件名中,则会发生不好的事情。那是因为你永远不能通过名称来引用这个文件 :( 因为任何时候你这样做,Linux 都会假设你引用的是一个不存在的目录。使用 'rm *' 技术也不起作用,因为 bash 只是将它扩展为文件名。 Evenrm -rf行不通,因为一个简单的 strace 揭示了事情是如何在引擎盖下进行的(缩短):

$ ls testdir
myfile2 out
$ strace -vf rm -rf testdir
...
unlinkat(3, "myfile2", 0)               = 0
unlinkat(3, "out", 0)                   = 0
fcntl(3, F_GETFD)                       = 0x1 (flags FD_CLOEXEC)
close(3)                                = 0
unlinkat(AT_FDCWD, "testdir", AT_REMOVEDIR) = 0
...

请注意,这些调用unlinkat将失败,因为它们需要按名称引用文件。

于 2012-03-23T23:05:28.267 回答
43

假设您的文件系统支持它,您可以使用显示为“/”的 Unicode 字符(例如这个看似多余的字形)。

于 2012-03-23T22:30:53.103 回答
13

这取决于您使用的文件系统。一些比较流行的:

于 2012-03-23T22:33:39.807 回答
7

仅使用商定的编码。例如,您可以同意%将被编码为%%,这%2F意味着/. 访问此文件的所有软件都必须了解编码。

于 2012-03-23T22:31:44.227 回答
3

简短的回答是:不,你不能。由于目录结构的定义方式,这是必要的禁止。

而且,如前所述,您可以显示一个“看起来像”斜杠的 unicode 字符,但仅此而已。

于 2012-03-23T22:31:42.573 回答
3

一般来说,尝试在文件名中使用“坏”字符是个坏主意。即使您以某种方式管理它,它也往往会使以后难以使用该文件。文件系统分隔符完全不起作用,因此您需要选择一种替代方法。

您是否考虑过对 URL 进行 URL 编码然后将其用作文件名?结果应该可以作为文件名,并且很容易从编码版本中重建名称。

另一种选择是创建一个索引 - 使用您喜欢的任何方法创建输出文件名 - 顺序编号的名称、SHA1 哈希值等等 - 然后使用生成的文件名/U​​RL 对写入一个文件。您可以将其保存到散列中并使用它进行 URL-to-filename 查找,反之亦然,使用反向版本的散列,如果需要,您可以将其写出来并在以后重新加载。

于 2015-04-22T17:30:18.780 回答
2

简短的回答是:你不能。长答案是,您可能可以或者这取决于您从哪里查看它以及您正在使用哪个层。

由于问题中有Unix标签,我将回答Unix

正如其他答案中提到的那样,您不能在 filename 中使用正斜杠

但是,MacOS您可以通过以下方式创建带有正斜杠的文件/

# avoid doing it at all cost
touch 'foo:bar'

现在,当你从终端看到这个文件名时,你会看到它foo:bar

但是,如果您从finder: 中看到它,您会看到 finder 将其转换为foo/bar

同样的事情可以反过来做,如果你从 finder 创建一个带有正斜杠的文件,比如/foobar,将在后台完成转换。结果,您将:foobar在终端中看到,但从取景器中查看时则相反。

因此,:在 中有效unix layer,但它/在 Mac 层(如 Finder 窗口、GUI)中转换为或从其转换。:冒号用作分隔符,HFS paths斜杠/用作分隔符POSIX paths

因此,会发生双向转换,具体取决于您正在使用的“层”。

在此处查看更多详细信息:https ://apple.stackexchange.com/a/283095/323181

于 2021-01-13T08:35:33.770 回答
0

在 Linux 和 Unix 中,您可以使用带有 / 的文件名。这是一个非常古老的问题,但令人惊讶的是,自从提出这个问题以来,近 10 年都没有人说过这个问题。

每个 Unix 和 Linux 系统都有名为 / 的根目录。目录只是一种特殊的文件。符号链接、字符设备等也是特殊类型的文件。请参阅此处进行深入讨论。

您不能使用 / 创建任何其他文件,但您肯定有一个 - 并且是一个非常重要的文件。

于 2021-11-10T21:35:51.940 回答