文件名中可以使用 "/" 吗?

161

我知道这不是应该做的事情,但在Linux中是否有一种方法可以使用通常用于文件夹之间分隔符的斜线字符作为文件名的一部分?


1
我猜你可以通过直接访问硬盘分区并在某个位置添加'/'字符来修改文件名。会发生什么是一个有趣的问题...很可能不是你想要的结果。 - hochl
1
但简短的答案应该是:不,这不是应该做的事情 :-) - Simeon Visser
1
将斜杠插入文件名的目录条目中是否计入FS?这是不建议的,因为您将无法永久地访问该文件。 - Jonathan Leffler
59
这让我想起了我朋友曾经创建名为*的文件,然后问我:“怎么删除这个文件?” 我回答说,用rm命令加上文件名即可。你知道后面发生了什么。 - David Heffernan
3
对于新的Linux用户,当您对表达式或文件名不自信时,我认为使用ls列出要删除的文件,然后将ls命令更改为rm是一个好习惯。 - Dave F
8个回答

172
答案是你不能,除非你的文件系统存在一个错误。原因如下:
在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字符或者类似斜杠但实际上不是斜杠的东西。
  • 它们存在一个bug。
此外,如果你确实编辑了字节以在文件名中添加斜杠字符,会发生糟糕的事情。那是因为你永远无法通过名称引用这个文件 :( 因为每次你这样做,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的调用将失败,因为它们需要通过文件名来引用文件。

10
请注意,至少e2fsck将任何文件名视为非法文件名,并需要修复 - 请参见源代码。因此,如果您不小心遇到包含斜杠的文件名,可以使用fsck来解决问题。 - ehabkost
10
任何文件名?听起来像是 e2fsck 的一个 bug :p - flarn2006

52
您可以使用一个Unicode字符,它显示为/(例如分数斜线),假设您的文件系统支持它。

51
是的,确切地说:只有U+002F SOLIDUS斜线是被禁止的。还有很多其他合适的备选项:⁄ 是 U+2044 FRACTION SLASH;∕ 是 U+2215 DIVISION SLASH;⧸ 是 U+29F8 BIG SOLIDUS;/ 是 U+FF0F FULLWIDTH SOLIDUS,而 ╱ 则是 U+2571 BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT。它们都能完美地发挥作用! - tchrist
2
但是如果用户在他的文件/目录名称中使用了这些实际字符怎么办呢? 我们需要一个通用的转义解决方案。很遗憾,Linux的正常代码不支持任何转义,因为它只匹配ASCII 0x2F。 自至少20年以来,ASCII就已经过时了。(Unicode 1.0是从1991年开始的!) - anon
1
有关于在不同文件系统下禁止使用的多个字符的可能替换列表,请查看我的回答:https://dev59.com/snI-5IYBdhLWcg3wMFS0#61448658 - Cadoiz
1
这不是一个冗余的字形,而是为了不同的目的而设计的不同字符:比较1∕3和1/3。虽然在这种情况下替换仍然可以使用。 - LeopardShark
我的终端(Gnome默认)显示字符如此 https://i.stack.imgur.com/JSBzu.png,而Dolphin文件管理器则以这种方式显示 https://i.stack.imgur.com/5Qhfy.png。 - user598527
显示剩余2条评论

16

2
它不仅取决于文件系统,所有*nix系统中的系统调用都会将/解析为目录树的组成部分。 - Blackle Mori
3
正斜杠字符在内核中是硬编码的,与文件系统无关(尝试在内核源代码中执行 grep -r "'/'" *)。 - Robert Martin
21
抱歉,"正斜杠"是一个完全可以接受的方式来指代斜杠字符,以便清楚地表明所指的是哪一个斜杠。有时候人们会感到困惑 :P - Robert Martin
2
哈哈,但我认为@tchrist也有一点道理。为什么“forward”意味着“/”,而“back”意味着“\”?到目前为止,我最好的解释是,如果用笔从下往上在一条线上写,从左到右阅读/写作,“/”向右移动或“向前”,而“\”向左移动或“向后”。不过,我并不喜欢这个解释,部分原因是我并不总是从底部开始书写字符然后向上移动。我认为从顶部开始向下书写字符通常更流畅。 - Jesse W. Collins
7
这只是一个侧面的问题,但这是标准的、规范化的语言。" Slash "不是Unicode所称的那些符号,Unicode称它们为“solidus”,而“\”是反斜杠,与“向后”的意思相同,因此称为“backslash”。如果需要证明,back和forward是线条倾斜或应该落下的方向,根据书写方向(从左到右)来确定方向。如果看起来像“\”,则它会倾斜或应该向<==或者向后落下;如果看起来像“/”,则它会倾斜或应该向==>或者向前落下。 - Stuart R. Jefferys

8
只有经过协商的编码才可以。例如,您可以达成一致,%将被编码为%%,而%2F将表示/。所有访问此文件的软件都必须了解编码。

20
无论用什么名字来称呼我们所谓的“斜线”,它都会散发出同样恶臭的气味。-- 莎士比亚 - Robert Martin

4
一般来说,尽量不要在文件名中使用“坏”字符,即使你设法成功了,也很难在以后使用该文件。文件系统分隔符根本不会起作用,因此您需要选择替代方法。
您考虑过对URL进行编码,然后将其用作文件名吗?结果应该作为文件名很好,并且可以从编码版本轻松重构名称。
另一个选择是创建索引-使用任何您喜欢的方法创建输出文件名-按顺序编号的名称、SHA1哈希等-然后编写一个文件,其中包含生成的文件名/ URL对。您可以将其保存到哈希中,并使用它进行URL-to-filename查找或反之亦然,使用哈希的反向版本,并且如果需要,可以将其写出并重新加载。

3
简短的回答是:不可以。详细回答是,可能可以或取决于您从哪个层面查看它以及您使用的层面。
由于问题中有Unix标签,我将为Unix回答。
如其他答案所述,您不要在文件名中使用正斜杠
但是,在MacOS中,您可以通过以下方式创建一个带有正斜杠/的文件:
# avoid doing it at all cost
touch 'foo:bar'

现在,在终端中看到这个文件名,你会看到它是foo:bar
但是,如果你从Finder中查看它:你将看到Finder将其转换为foo/bar
同样的事情也可以反过来做,如果你在Finder中创建一个包含正斜杠的文件,比如/foobar,那么后台会进行一次转换。结果,在终端中你会看到:foobar,但是从Finder中查看则是另一种方式。
因此,:在Unix层中是有效的,但在Mac层中(如Finder窗口、GUI)却被翻译成或者从/翻译而来。在HFS路径中,冒号:被用作分隔符,在POSIX路径中,斜线/被用作分隔符。
因此,根据你使用的“层”,会发生双向翻译。
更多详情请参见:https://apple.stackexchange.com/a/283095/323181

3
在Linux和Unix中,文件名可以包含/。这是一个非常古老的问题,但令人惊讶的是,在近10年来自问问题以来,没有人提到过这一点。
每个Unix和Linux系统都有名为/的根目录。目录只是一种特殊类型的文件。符号链接、字符设备等也是特殊类型的文件。有关详细讨论,请参见此处
您不能创建任何其他带有/的文件,但您肯定有一个非常重要的文件。

“/” 绝对是一个路径,但它是否是一个文件呢? - kravemir
这是一个目录。而且在Unix中,目录(像许多其他东西一样)也是一个文件。 - George

3
简而言之,不行。这是因为目录结构的定义所必需的禁止。但是你可以显示类似斜杠的Unicode字符,但也仅此而已。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接