是否可以在文件名中使用“/”?

时间:2012-03-23 22:28:14

标签: linux unix directory filenames slash

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

7 个答案:

答案 0 :(得分:115)

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

系统调用重命名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只是将它扩展为文件名。即使rm -rf也行不通,因为一个简单的线索揭示了事情的发展方式(缩短):

$ 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的这些调用会失败,因为他们需要按名称引用这些文件。

答案 1 :(得分:30)

您可以使用显示为“/”的Unicode字符(例如this seemingly redundant glyph),假设您的文件系统支持它。

答案 2 :(得分:7)

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

答案 3 :(得分:3)

仅限商定的编码。例如,您可以同意将%编码为%%%2F将表示/。访问此文件的所有软件都必须了解编码。

答案 4 :(得分:1)

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

并且,如上所述,您可以显示"看起来像"的unicode字符。斜线,但就你而言。

答案 5 :(得分:1)

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

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

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

答案 6 :(得分:0)

简短的回答是:你不能。长的答案是,您可能可以,或者这取决于您从何处查看它以及您在哪个图层中工作。

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

正如其他答案中提到的,您不得在文件名中使用正斜杠

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

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

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

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

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

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

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

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