是否可以在文件名中使用“/”?
我知道这不是应该做的事情,但有没有办法使用通常在Linux中分隔文件名中的目录的斜杠字符?
答案是,你不能,除非你的文件系统有一个错误。 原因如下:
有一个系统调用重命名您在fs/namei.c
定义的名为renameat
:
SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname)
当系统调用被调用时,它会在名称上进行path查找( 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; ...
此代码适用于任何文件系统。 这是什么意思? 这意味着如果你尝试用传统的方法传递一个带有实际'/'
字符的参数作为文件的名字,它将不会做你想要的。 没有办法逃避angular色。 如果一个文件系统“支持”这个,那是因为它们是:
- 使用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
将表示一个/
。 所有访问这个文件的软件都必须理解编码。
这取决于您正在使用的文件系统。 一些比较stream行的:
- ext3: 没有
- ext4: 没有
- jfs: 是的
- reiserfs: 不
- xfs: 不
简短的回答是:不,你不能。 由于如何定义目录结构,这是一个必要的禁止。
而且,如前所述,您可以显示一个unicode字符,“看起来像”斜线,但这是你得到的。
一般来说,尝试在文件名中使用“坏”字符是一个坏主意; 即使你以某种方式pipe理它,也往往使得以后很难使用这个文件。 文件系统分隔符是完全不起作用的,所以你需要select另一种方法。
你有没有考虑URL编码的url,然后用它作为文件名? 结果应该是一个很好的文件名,并且很容易从编码版本重build名称。
另一个select是创build一个索引 – 使用任何你喜欢的方法创build输出文件名 – 按顺序编号的名字,SHA1哈希值,然后用所生成的文件名/ URL编写一个文件。 你可以把它保存到一个散列中,并用它来做一个URL到文件名的查找,反之亦然,反之亦然,如果需要,你可以把它写出来并重新加载。