【发布时间】:2021-11-06 06:52:29
【问题描述】:
将目录路径定义为变量或常量时,是否应该以斜杠结尾?约定是什么?
Unix 中的pwd 显示您的当前目录时没有尾部斜杠,而cd /var/www/apps/ 的制表符完整包含尾部斜杠,这让我不确定。
【问题讨论】:
将目录路径定义为变量或常量时,是否应该以斜杠结尾?约定是什么?
Unix 中的pwd 显示您的当前目录时没有尾部斜杠,而cd /var/www/apps/ 的制表符完整包含尾部斜杠,这让我不确定。
【问题讨论】:
我使用斜杠是因为:
“如果它以斜杠结尾,它是一个目录。如果不是,它是一个文件。”是一个容易记住的约定。
至少在我常用的操作系统上,双斜线不会导致问题,而省略斜线会导致大问题。因此,将斜杠放入变量中并在使用时使用"$path/$file" 是最安全的。
【讨论】:
A pathname that begins with two successive slashes may be interpreted in an implementation-defined manner, although more than two leading slashes shall be treated as a single slash. 在大多数情况下,在常见的实现中,双斜杠通常被解释为单斜杠。
例如,当我定义一个用于存储文件的目录时,我不包括尾部斜杠。那是因为我会像这样使用它
$store_file = "$store_path/$file_id";
在使用应该包含目录路径的变量之前,我总是会添加一个斜杠。我认为总是添加一个比怀疑是否包含尾部斜杠要好。
【讨论】:
'///' + $root + '//' + $file + '/' 的东西,这并不重要。尽管使用尾部斜杠是辨别路径是文件还是目录的好方法,但最好附加到 '/' + $root 而不是 $root + '/' 这样的路径,因为您不能肯定该路径是appended 有一个斜杠,但您可以相对放心,在大多数环境中,多个斜杠将被解释为单个斜杠。
/tmp/store_data/ 是一个目录,但不清楚没有斜杠的相同路径是什么/tmp/store_data
rm -rf $foo/$bar可以以rm -rf /结尾
我知道这是 10 岁,但我想投入我非常固执的 0.02 美元。
没有。没有。绝对没有。
我们谈论的是 Unix 系统。就目录本身而言,它是一个与其他任何节点一样的节点。在引用目录时,它的名称中不应包含未转义的斜杠(参考:dirname、pwd、~、echo $HOME、echo $PATH、ls 的输出等) .
当引用目录的内容时,那么你需要一个斜杠。也就是说,ls /home/karl/ 比ls /home/karl 更合适(FTR,我几乎总是做后者,因为...好吧,懒惰)。
当使用包含目录的变量来创建文件的完整路径时,您总是希望包含斜杠(即:cp ${HOME}/test ${OTHER_DIR}/)。
预计目录不以斜线结尾。对目录以斜线结尾的任何期望都是错误的。因此,在*_DIR 变量值的末尾添加一个斜线将颠覆预期。
至于制表符补全,这里的期望是您将进入 那个目录。因此,tab 补全提供的帮助是让您进入该目录,以便您可以根据其内容做出下一个选择。
(来自 cmets:Filepath Misconceptions,来自维基百科的 Talk:Path_(computing) 页面。谢谢,john c. j.)
值得注意的是,仅仅因为它是错误的并不意味着工具/包/库永远不会这样做。这种情况太常见了,当这些东西不应该存在时,会添加一个斜杠。因此,正如Bevan 和Paul F 都建议的那样,在使用第三方工具时,最好删除目录名称中可能存在的任何尾部斜杠。
Unix 索引节点
inode(索引节点)是 Unix 风格文件系统中的一种数据结构,用于描述文件系统对象,例如文件或目录。
-- https://en.wikipedia.org/wiki/Inode
文件系统层次标准
Unix 文件系统标准(Filesystem Hierarchy Standard,AKA FHS)清楚地表明目录不被认为具有尾部斜杠,而是目录内容以斜杠开头(唯一的/ 是个例外,因为我们不会使用空字符串来引用文件系统根目录……而且无论如何都不应该在那里创建文件。)
-- http://www.pathname.com/fhs/pub/fhs-2.3.html
-- https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard
【讨论】:
/ 打破了这种模式。如果您要从这里(递归地)开始推理,那么您就可以找到可能是不同实践核心的矛盾(正如这里的答案所证明的那样)。但是一旦你接受了这个例外,那么其他一切都会顺理成章。
是的,应该这样:
路径名 + 文件名 = 完全限定的文件位置。
所以最后一个目录和文件名之间的斜线需要在路径名的末尾或文件名的开头。使用 / 为文件名添加前缀意味着如果您只想打开一个文件(即,如果您假设当前工作目录中有一个不合格的文件名),则需要考虑这一点。
【讨论】:
每当我存储目录路径或从 API 返回它们时,我都会尝试遵守保留斜杠的惯例。这避免了整个“是文件还是目录”的歧义。
附录:
这并不是要替代使用可以容忍尾部斜杠或不存在斜杠的方法。即使使用这种约定,我仍然总是使用Path.Combine(...) 和类似的方法。
【讨论】:
os.path.join(dir, subdir_or_file)
也许您应该考虑一下您的决定对文件意味着什么。如果您没有在 directory 名称的末尾包含斜杠,则必须将其添加到 file 名称的开头。
现在,如果由于某种原因,在您连接字符串时缺少指向该文件的路径,您最终会得到类似 /filename 的东西,这不仅仅是一个文件,而是根目录的绝对路径(无论可能是在那种情况下)。
这就是为什么我用斜杠结束我的路径并将文件保存为文件。
【讨论】:
./filename。但总的来说,连接路径的代码应该负责正确地执行此操作 - 而不是以任何方式做出假设。
我知道这是一个旧线程,但我想我会分享我的工作。如果可能的话,我通常会允许两者并做这样的事情(如果是 PHP):
$fullPath = rtrim($directory, '/') . '/filename.txt');
这样,如果目录是在配置文件中定义的,那么下一个更改它的人是否包含尾部斜杠都没有关系。
【讨论】:
在 php 中,由于 dirname(__FILE __) 函数返回的目录名称末尾没有斜线。我倾向于坚持那个约定。
否则,在目录名末尾使用斜杠会与 dirname(..) 的工作方式发生冲突,然后您将无法处理这两种情况,因为您不知道目录名是否来自 dirname (..) 函数或用斜杠定义的内容。
底线:不要使用尾部斜杠,因为 dirname(..) 没有。
// PHP Example
dirname(__FILE__); // returns c:\my\directory without a trailing slash, so stick to it!
对于其他语言,检查提取路径名的函数,看看它是否使用了斜杠,然后遵守语言的约定。
【讨论】:
我倾向于只添加尾部斜杠,因为我很可能会使用该目录来添加/检索文件...
就网络引用而言,它实际上可以提高性能,而将尾部斜杠留在
【讨论】:
是的,有很多文件系统支持没有任何扩展名的文件,因此请始终添加尾部斜杠以避免任何问题。
【讨论】:
无论哪种方式,我都从未见过固定的约定。
不过,可以肯定的是,无论您选择什么,其他人都会 100% 确定它应该是另一种方式。所以,最好的办法是容忍任何一种方式设置。
在 .NET 世界中,Path.Combine() 为您提供了一种处理此问题的方法 - 从 cmd 文件开始,在其他环境中也有等价物。
【讨论】:
约定是一致的。重要的是,要意识到关于 / 是否属于目录或文件名的论点是错误的二分法;它不属于任何一个,因为它是路径分隔符。
IMO 的正确答案是,如果路径操作库由您的语言提供(或编写您自己的语言),您应该尽可能使用路径操作库,并忽略路径的内部结构,因为它看起来像一个字符串。这将消除知道在哪里放置斜线的问题,并且还可以使您的代码在系统之间更具可移植性。
【讨论】:
我想这是少数情况下正确的理论和实践答案不同的情况之一。
似乎@Karl Wilbur 的answer 在理论上肯定是正确的,因为您应该能够区分对目录节点本身的引用与目录的内容。
但在实践中,我认为正确的答案是相反的:
最重要的原因是您可以通过 确定性 判断路径 /home/FSObjectX/ 是一个文件夹,而 /home/FSObjectX 是不明确的。没有人知道这是否是文件夹中的文件。
规范应始终准确无误。
在绝大多数情况下,您将始终引用文件夹的内容,而不是 dir 节点本身。
在您实际这样做的极少数情况下,可以通过删除任何可选的来轻松地在代码中处理它尾随 dir 分隔符。
使用双 dir-separators 不会造成任何伤害,但肯定会丢失一个。
从理论上讲,这是一个不好的论点,因为您不应该“偶然”编码,但在实践中,会发生错误,并且可能使用尾随 dir-sep 最终可能会在最终用户处减少一些运行时错误。
通读这个有趣的帖子,我没有发现使用尾随 dir-sep 的任何缺点,只是在理论上它是错误的。还是我错过了什么?
【讨论】:
$homedir = "/home/FSObjectX";,我会相当肯定它是一个目录。如果我感觉特别不信任,我可以要求文件系统进行验证。规范确实需要精确和明确,但/home/FSObjectX/ 明确是对内容的引用,/homeFSObjectX 明确是对许多规范中节点的引用。花几个小时玩rsync 来真正了解其中的区别:)