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

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

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

有一个系统调用重命名您在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也行不通,因为一个简单的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调用会失败,因为它们需要按名称来引用这些文件。

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

只有一个商定的编码。 例如,您可以同意%将被编码为%%%2F将表示一个/ 。 所有访问这个文件的软件都必须理解编码。

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

  • ext3: 没有
  • ext4: 没有
  • jfs: 是的
  • reiserfs: 不
  • xfs: 不

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

而且,如前所述,您可以显示一个unicode字符,“看起来像”斜线,但这是你得到的。

一般来说,尝试在文件名中使用“坏”字符是一个坏主意; 即使你以某种方式管理它,也往往使得以后很难使用这个文件。 文件系统分隔符是完全不起作用的,所以你需要选择另一种方法。

你有没有考虑URL编码的网址,然后用它作为文件名? 结果应该是文件名,并且很容易从编码版本重建名称。

另一个选择是创建一个索引 – 使用任何你喜欢的方法创建输出文件名 – 按顺序编号的名字,SHA1哈希值,然后用所生成的文件名/ URL编写一个文件。 你可以将它保存到一个散列中,并用它来做一个URL到文件名的查找,反之亦然,反之亦然,如果需要的话,可以写出来并重新加载。