路径组件的命名标准是什么?

310

当我在处理路径和文件名时,由于没有遵循命名标准,我总是会搞混自己。

考虑下面这个玩具问题(Windows示例,但答案应该与平台无关)。你已经获得了一个文件夹的路径:

C:\Users\OddThinking\Documents\My Source\
你想要遍历所有子文件夹并将所有的 .src 文件编译成 .obj 文件。 有时你会看到以下路径:
C:\Users\OddThinking\Documents\My Source\Widget\foo.src

你会如何命名以下路径组件?

A. foo
B. foo.src
C. src
D. .src
E. C:\Users\OddThinking\Documents\My Source\ (absolute path of the root)
F. Widget\foo.src (relative path of the file to absolute path of the root)
G. Widget\
H. C:\Users\OddThinking\Documents\My Source\Widget\
I. C:\Users\OddThinking\Documents\My Source\Widget\foo.src

这是我的尝试:

A. 基本名称?文件基本名称?

B. 文件名称?文件名?
在选择标识符名称时,区别很重要,但在这里我从未保持一致。

C. 扩展名?

D. 扩展名?等等,这就是我所谓的C。
我应该避免存储点,并在必要时添加它吗?
如果某个文件上没有点怎么办?

E. ?

F. ?

G. 文件夹?但这不是一个特定于Windows的术语吗?

H. 路径名称?路径名?路径?

I. 文件名称?等等,这就是我所谓的B。
路径名称?等等,这就是我所谓的H。


微软的技术编辑Mike Pope在他的博客上指出,尽管微软的样式指南始终坚持两个单词:文件名、文件夹名、卷名,但苹果样式指南有时会将它们合并为一个单词:filename、pathname、volume name。 - Oddthinking
A) 应该绝对不被称为basename,因为basename已经在许多地方用于表示路径中的最后一项(对于文件来说,这将是没有dirpath的文件名)。有些地方将没有扩展名的文件名称为“stem”。 - wisbucky
另外,对于具有多个句点的文件(例如foo.src.txt),是否有任何标准方法来识别(和命名)扩展名? - user117529
9个回答

235
我认为你对“标准”命名约定的搜索将是徒劳的。以下是我的建议,基于现有的、众所周知的程序。
A) C:\users\OddThinking\Documents\My Source\Widget\foo.src
                                                   ---

Vim 称之为“文件根目录” (:help filename-modifiers)
B) C:\users\OddThinking\Documents\My Source\Widget\foo.src
                                                   -------
文件名或基本名称
C) C:\users\OddThinking\Documents\My Source\Widget\foo.src
                                                       ___ (without dot)
文件/名称扩展名
D) C:\users\OddThinking\Documents\My Source\Widget\foo.src
                                                      ____ (with dot)

也是文件扩展名。如果文件没有点,就直接存储,它就没有扩展名。
E) C:\users\OddThinking\Documents\My Source\Widget\foo.src
   -----------------------------------------

树顶 没有惯例,git称之为“基础目录”
F) C:\users\OddThinking\Documents\My Source\Widget\foo.src
                                            --------------

从树顶到叶子的路径 相对路径
G) C:\users\OddThinking\Documents\My Source\Widget\foo.src
                                            ------

树的一个节点 没有约定,可能是一个简单的目录
H) C:\users\OddThinking\Documents\My Source\Widget\foo.src
   ------------------------------------------------
目录名称
I) C:\users\OddThinking\Documents\My Source\Widget\foo.src
   -------------------------------------------------------
完整/绝对路径

10
离题了,但要注意将扩展名与点分开的存储方式。您需要处理文件名为“foo”、“foo.”和“foo.txt”(甚至是“foo.txt.bak”)的情况。 - Oddthinking
2
嗨大家,很好的例子。如果您将答案放在问题旁边而不是使用需要向上卷动的引用,阅读会更容易。顺便说一下,我进行了编辑以改进它。问候 - Victor
3
维克多,由于你的编辑被拒绝了(天啊,伙计们,这是一个非常好的改进!),所以我自己做了这个编辑 :-) - blinry
1
对于 1.(仅文件名,不包括扩展名),由于缺乏明确的约定或至少全球共识,我早就决定采用 文件标题 - polyvertex
1
对于没有扩展名的文件名A,您可以使用stem。参考文献:https://doc.rust-lang.org/std/path/struct.Path.html#method.file_stem,http://llvm.org/docs/doxygen/html/namespacellvm_1_1sys_1_1path.html#a498ae7b56cdff5b5b3d8f78ed94ac640,http://www.boost.org/doc/libs/1_60_0/libs/filesystem/doc/reference.html#path-decomposition - wisbucky
显示剩余5条评论

42
首先是一个好问题,我会支持。在创建Utility类时,GetFileName?或者GetFullName? GetApplicationPath是指全路径还是目录名?这些问题一直困扰着我。我来自.NET背景,所以我认为我可以为@blinry的优秀回答增加一点内容。 总结:(斜体表示作为程序员我不会使用的)
  1. 路径:路径指定文件系统中的唯一位置(除非它是相对路径)。路径名不经常使用,但我会坚持使用路径 - 它几乎解释了它是什么。路径可以指向文件、文件夹甚至是空文件夹(C:\)。路径可以是:

    1. 相对路径My Source\Widget\是相对路径,Widget\foo.src也是相对路径。很容易理解。
    2. 绝对路径完整路径:是指完全限定的指向目标的路径。我更倾向于使用后者。C:\users\OddThinking\Documents\My Source\Widget\foo.src因此是完整路径。请看最后一个我称之为指向文件并以目录结尾的完整路径。

    维基页面和.NET的路径命名是一致的。

  2. 根路径根目录:前者是.NET惯例,而后者在UNIX界更为流行。虽然我都喜欢,但我更倾向于使用前者。与UNIX不同,在Windows中有许多不同的根路径,每个分区一个。Unix系统有一个根目录,存放其他目录和文件的信息。例如:C:\就是根路径。

  3. 文件夹文件夹名称:在你的情况下,如WidgetOddThinking等。这可能只是Windows的约定(实际上这是我自己的奇怪想法:)),尽管对于普通用户来说,目录和文件夹(如子文件夹、子目录)是相同的,但我认为从技术角度来看,“目录”应该听起来像一个指向目标的合格地址,而不是目标本身。下面详细说明。

  1. 子文件夹: 相对于usersOddThinkingDocuments是子文件夹。
  2. 子目录: 相对于usersOddThinking\OddThinking\Documents\OddThinking\Documents\My Source\Widget\是子目录。但我们通常不需要过多关注它,对吧?
  3. 子文件夹: 相对于usersOddThinking是一个子文件夹(也是一个子文件夹)。
  4. 父文件夹: 对于OddThinking来说,users是其父文件夹(只是提及不同的术语,并没有什么大不了的)。
  • 目录目录名: 一般在现实生活中使用前者,在代码中使用后者。这指的是到目标父文件夹的完全限定路径(或简称完整路径)。在你的情况下,路径为:C:\users\OddThinking\Documents\My Source\Widget(是的,目录永远不应该指向文件)。我在我的代码中使用目录名,因为在.NET中目录是一个类,而目录名是库本身所称之。它相当一致,并与UNIX系统中使用的dirname非常相似。

  • 文件名基本名称: 文件名及其扩展名。在你的情况下为:foo.src。对于非技术用途,我更喜欢使用文件名(这是对最终用户的意思),但对于技术目的,我会严格坚持使用基本名称。文件名通常由MS使用,但我很惊讶他们不仅在文档中而且甚至在库中都没有保持一致。在那里,文件名可能意味着文件的基本名称或完整路径。因此,我更喜欢使用基本名称,在我的代码中就是这样称呼它们的。 此页面上的维基百科也说文件名可以指全路径或基本名称。令人惊讶的是,即使在.NET中,我也可以找到使用基本名称表示文件根名称的用法。

  • 扩展名文件名扩展名文件扩展名:我喜欢最后一个。所有的都指的是同一件事,但它到底是什么又是一个争论的问题!维基说它是 .src,但我记得以前读过许多语言解释它为 .src。注意点号。所以我的看法还是,对于非正式使用,它不重要是什么,但作为程序员,我总是把扩展名看作是 .src

    好吧,我可能试图获取一些标准用法,但这里有两个我遵循的约定。而且是关于完整路径的。

    1. 我通常将指向文件的完整路径称为文件路径。对我来说,文件路径很清楚,它告诉我它是什么。虽然对于文件名,我认为它是文件的名称,在我的代码中我将其称为文件名。这也与"目录名"保持一致。从技术角度来看,名称指的是完全限定名称!令人沮丧的是,.NET使用文件名(因此我在这里有我的观点),有时还使用文件路径。

    2. 我将以目录结尾的完整路径命名为目录。实际上,任何不指向文件的地址都可以称为目录。因此,C:\users\OddThinking\Documents\My Source\ 是一个目录,C:\users\OddThinking\ 是一个目录,甚至是 OddThinking\Documents\My Source\(最好称之为子目录或更好的相对路径-所有这些取决于您处理它的上下文)。上面提到了有关目录名称的不同内容。这是我的看法:我将获取一个新路径以避免混淆。这个 D:\Fruit\Apple\Pip\ 是什么?一个目录。但如果问题是 D:\Fruit\Apple\Pip\ 的目录或更好地说是目录名称是什么,则答案是 D:\Fruit\Apple\。希望清楚了。

    我会说最好不要担心最后两个术语,因为这是最容易引起混淆的部分(对我个人而言)。只需使用术语完整路径即可!

  • 回答你的问题:

    1. 关于您给出的路径

      A) 不知道。无论如何,我从未需要单独获取它。

      B) basename

      C) 我只会称其为文件扩展名,暂时不用担心,因为我从未需要在代码中单独命名它。

      D) 当然是文件扩展名。

      E) 我认为这不是一个通用的要求。不确定。在.NET中,基本目录与目录名称相同。

      F) 相对路径

      G) 文件夹(基名 foo.src 的父文件夹)

      H) 目录名称

      I) 完整路径(甚至包括文件名)

    2. 一般而言(抱歉有点啰嗦,只是为了强调),但假设foo.src确实是一个文件

      A) NA

      B) 基名

      C) NA

      D) 扩展名

      E) 目录或路径

      F) 相对路径

      G) NA

      H) 目录或路径

      I) 完整路径(甚至包括文件名)

    接下来举个例子:

    1. 考虑路径C:\Documents and Settings\All Users\Application Data\s.sql

      1. C:\Documents and Settings\All Users\Application Data\s.sql 是完整路径(也是文件名)
      2. C:\Documents and Settings\All Users\Application Data\是目录名称。
    2. 现在考虑路径C:\Documents and Settings\All Users\Application Data

      1. C:\Documents and Settings\All Users\Application Data是完整路径(这恰好是一个目录)
      2. C:\Documents and Settings\All Users是目录名称。

    我的两个提示:

    1. 我遵循这样的经验法则,即在涉及无论其类型如何的全地址时,我几乎总是称其为“完整路径”。这不仅消除了用于文件路径和文件夹路径两种术语的使用,而且还避免了潜在的混淆,如果您要将其命名为文件名(对于大多数用户来说,这立刻转化为基名)。 但是,如果您必须具体说明路径的类型,最好将其命名为文件名或目录而不是更通用的“路径”。

    2. 无论您打算使用什么样的想法,请始终保持一致。 在团队成员之间达成共识,明确这意味着什么而不是那个。

    现在,仅仅从这个圈子中,我就有了一些实践。新品牌的术语将是 OS X 和 Android 设备上使用的术语。所有这些都只涉及文件系统中的物理路径。关于 Web 地址,将出现一整套新的术语。我期望有人在同样的主题中填补空白 :) 我很高兴听到您所采用的惯例。


    长期以来,我一直使用“路径名”这个词来表示包括完整文件名在内的整个绝对路径。您的回答、其他人的意见以及其他资源改变了我的看法,现在我将使用“全路径”来表示这个概念,“路径”表示不包括文件名的位置,“文件名”或“名称”表示文件名本身。 - Nate

    37
    在 C++ 中,Boost.Filesystem 为路径的各个部分设计了一个命名规范。有关详细信息,请参阅 path decomposition 参考文档以及此 tutorial。以下是基于教程的摘要:
    • Windows 路径:c:\foo\bar\baa.txt
    • Unix 路径:/foo/bar/baa.txt
    对应的结果如下:
    Part            Windows          Posix
    --------------  ---------------  ---------------
    Root name       c:               <empty>
    Root directory  \                /
    Root path       c:\              /
    Relative path   foo\bar\baa.txt  foo/bar/baa.txt
    Parent path     c:\foo\bar       /foo/bar
    Filename        baa.txt          baa.txt
    Stem            baa              baa
    Extension       .txt             .txt
    

    C++标准ISO/IEC 14882:2017

    此外,Boost.Filesystem术语已被采用于C++17 => 请参见std::filesystem

    Function name     Meaning
    ----------------  -------------------------------
    root_name()       Root-name of the path
    root_directory()  Root directory of the path
    root_path()       Root path of the path
    relative_path()   Path relative to the root path
    parent_path()     Path of the parent path
    filename()        Path without base directory (basename)
    stem()            Filename without extension
    extension()       Component after last dot
    

    8
    那么他们如何称呼整个东西呢?pathfullpath - wisbucky
    2
    @wisbucky 在他们的术语中,整个东西被称为“路径”。 - Emile Cormier
    1
    @wisbucky 已修复链接。谢谢。 - Emile Cormier
    @olibre:感谢C++17的更新。但是stem()是文件名的一部分,而不是路径的一部分。 - Emile Cormier
    3
    @johnc.j. 很遗憾,当初提出这个问题时Boost.Filesystem并不是那么出名。我宁愿采用同行评审库的命名法,也不愿自己凭空想出一个名字。 - Emile Cormier
    显示剩余4条评论

    22

    Python中的Pathlib标准库遵循以下路径组件的命名约定:

    路径 描述
    A. /x/y/z.tar.gz 主干
    B. /x/y/z.tar.gz 名称
    C. /x/y/z.tar.gz(不包括点) N/A
    D. /x/y/z.tar.gz(包括点) 后缀
    E. /x/y/z.tar.gz 上级路径
    F. /x/y/z.tar.gz 相对于上级路径的路径
    G. /x/y/z.tar.gz 父级名称
    H. /x/y/z.tar.gz 父级路径
    I. /x/y/z.tar.gz 路径

    我想采用这个方法,但是使用“后缀”而不是“扩展名”,这个概念从哪里来的?看起来很不直观。 - run_the_race
    文档中说:“PurePath.suffix是最终组件的文件扩展名(如果有的话):”我可以说我想称它为“shortyendthing”,并将其视为同义词。 Path.extension不存在。我知道它的作用,但不明白为什么他们为现有概念创造了一个新名称。 - run_the_race

    8

    您没有疯。

    在Windows系统中,有时候包含文件的目录路径被称为“路径”,这一点从一开始就是如此。因此,例如:

        x:\dir1\dir2\myfile.txt
    
        Windows:
        --------
            PATH:  x:\dir1\dir2
            FILE:  myfile.txt
    
        Unix/Linux:
        -----------
            PATH:  /dir1/dir2/myfile.txt
            FILE:  myfile.txt
    

    Unix/Linux的方法更加合乎逻辑,这也是所有人提到的:路径包含文件名本身。然而,在Windows命令行中键入“call /?”时,您会得到以下内容:
        %~1         - expands %1 removing any surrounding quotes (")
        %~f1        - expands %1 to a fully qualified path name
        %~d1        - expands %1 to a drive letter only
        %~p1        - expands %1 to a path only
        %~n1        - expands %1 to a file name only
        %~x1        - expands %1 to a file extension only
    

    所以,有"仅路径"和"仅文件名"两种形式。同时,它们将整个字符串称为"完全限定路径名",这被理解为驱动器字母加上路径加上文件名。所以没有真正的事实。这是徒劳无功的。你已经受到了背叛。
    总之,
    回答你的问题,
    我会这样命名你的例子:
    A: -
    B: basename
    C: extension
    D: -
    E: -
    F: -
    G: -
    H: pathname (or dirname or containing path)
    I: full name
    

    A-D-E-F没有简单的昵称。由于php可能是最广为人知的跨平台语言,每个人都会理解"basename"和"dirname",因此建议使用这个命名。全名也很明显;完整路径可能有点模糊,但大多数情况下它意味着完全相同的东西。


    1
    长期以来,我一直使用“路径名”这个词来表示包括完整文件名在内的整个绝对路径。这里和其他资源的答案改变了我的想法,现在我会使用“全路径”来表示这个概念,“路径”表示不包括文件名的位置,“文件名”或“名称”表示文件名本身。 - Nate

    4

    我十年的黑客经验告诉我:

    • 保持一致性
    • 思考递归

    输入图像描述

    以Windows机器为例:

    File separator: \ 
    Line separator: 
    
    Base name: file 
    Extension: txt 
    Filename: file.txt     
    
    Drive name: C 
    Root name: C: (empty on linux) 
    Root dir: \ 
    Root path: C:\     
    
    Base dir: Source\ 
    Base path: C:\Source\ 
    Sub dir: project\ 
    Sub-sub dir: docs\ 
    Relative dir: project\docs\     
    
    Relative path: project\docs\file.txt 
    Working dir: C:\Source\project\docs\
    Full path: C:\Source\project\docs\file.txt (also 'Absolute path' or 'File path')   
    
    Linux drive dir: C\ 
    Linux root path: \C\ 
    Linux base path: \C\Source\     
    
    Parent dir: ..\ 
    Current dir: .\
    

    底部附近的Linux内容是bash如何在Windows系统上挂载驱动器。

    当前目录或工作"目录"实际上是您的程序所在位置,但让我们使用它来跟踪正在处理的当前文件位置。在powershell中键入pwd,结果称为路径!

    目录始终以文件分隔符结尾,不包括文件名。它们可以很容易地添加。"目录名称"可能指任何位置的任何目录(dirName + sep = dir)。

    路径包括根、文件名或两者都包括。

    也就是说,“路径可以通过将根、文件名或两者添加到目录中而形成”。(您可以区分“路径”和“文件路径”,“相对路径”将排除文件名但提供基本目录到工作目录的目录,虽然术语变得多余,因为这正确地称为相对目录)。

    请注意关键字的不同含义:

    • name 姓名
    • directory 目录
    • path 路径
    • separator 分隔符

    然后,将这些与完整路径的各个部分组合起来:

    • root 根
    • base 基础
    • relative 相对
    • file 文件

    例如:根路径=根名称+根目录

    请注意,这适用于Windows和Linux(其中根路径与根目录相同,因为根名称为空)。


    在Java中,输出由以下方式产生:

    package io;
    
    import java.io.File;
    import java.util.logging.Logger;
    
    /**
     * Directory, File, and Path conventions.
     *
     * Directories always end with the file separator and never include the filename. They can easily be appended.
     * - "Directory name" could refer to any directory in any position (dirName + sep = dir).
     *
     * Paths include the root, the filename, or both.
     *
     * <em>On Windows, base directory names can be capitalised.</em>
     */
    public class Main {
        private static Logger logger = Logger.getLogger("io");
    
        public static void main(String[] args) {
            final String sep = File.separator;
            final String lf = System.lineSeparator();
    
            logger.info("File separator: " + sep);
            logger.info("Line separator: " + lf);
    
            String baseName = "file";
            String ext = "txt";
            String fileName = baseName + "." + ext;
    
            String driveName = "C";
    
            String rootName = driveName + ":";
            String rootDir = sep;
            String rootPath = rootName + rootDir;
    
            String baseDir = "Source" + sep;
            String basePath = rootPath + baseDir;
    
            String subDir = "project" + sep;
            String subSubDir = "docs" + sep;
            String relDir = subDir + subSubDir;
    
            String relPath = relDir + fileName;
            String workDir = basePath + relDir;
            String fullPath = basePath + relPath;
    
            logger.info("Base name: " + baseName);
            logger.info("Extension: " + ext);
            logger.info("Filename: " + fileName);
            logger.info(lf);
    
            logger.info("Drive name: " + driveName);
            logger.info("Root name: " + rootName + " (empty on linux)");
            logger.info("Root dir: " + rootDir);
            logger.info("Root path: " + rootPath);
            logger.info(lf);
    
            logger.info("Base dir: " + baseDir);
            logger.info("Base path: " + basePath);
            logger.info("Sub dir: " + subDir);
            logger.info("Sub-sub dir: " + subSubDir);
            logger.info("Relative dir: " + relDir);
            logger.info(lf);
    
            logger.info("Relative path: " + relPath);
            logger.info("Working dir: " + workDir);
            logger.info("Full path: " + fullPath + " (also 'Absolute path' or 'File path')");
    
            logger.info(lf);
            String linuxDriveDir = driveName + sep;
            String linuxRootPath = rootDir + linuxDriveDir;
            String linuxBasePath = linuxRootPath + baseDir;
            logger.info("Linux drive dir: " + linuxDriveDir);
            logger.info("Linux root path: " + linuxRootPath);
            logger.info("Linux base path: " + linuxBasePath);
    
            logger.info(lf);
            String parentDir = ".." + sep;
            String currDir = "." + sep;
            logger.info("Parent dir: " + parentDir);
            logger.info("Current dir: " + currDir);
        }
    }
    

    为回答问题,需要看OP的问题:
    A) foo = base name
    B) foo.src = file name
    C) src = extension
    D) .src = ? (file extension separator + extension)
    E) C:\users\OddThinking\Documents\My Source\ = base path
    F) Widget\foo.src = relative (file) path
    G) Widget = directory name
    H) C:\users\OddThinking\Documents\My Source\Widget\ = working path aka "working directory"
    I) C:\users\OddThinking\Documents\My Source\Widget\foo.src = full path, absolute path, file path
    

    2
    • foo 文件名(不含扩展名)

    • foo.src 文件名

    • src 扩展名

    • .src 可能是带点的扩展名,但不应使用。按照写法,这可能是目录名或文件名。

    • C:\users\OddThinking\Documents\My Source\ [绝对] 目录路径

    • Widget\foo.src 相对文件路径

    • Widget 目录名

    • C:\users\OddThinking\Documents\My Source\Widget\ 这仍然是一个[绝对] 目录路径。如果一个是根目录,另一个不是,则由变量名称来跟踪,实际上没有语义区别。

    • C:\users\OddThinking\Documents\My Source\Widget\foo.src [绝对] 文件路径

    “Filename”是一个单词,因此通常应使用“filename”而不是“file name”(以及Filename而不是FileName)。

    “Directory”一词可以用“Folder”代替。(也许我们应该在较低级别使用“Directory”,但我更喜欢“Folder”更短的长度。)

    实际上,可以创建所有这些类型的语义框架,并具有将它们组合的语义有效函数。例如,FolderNameFilename可以组合以给出RelativeFilePathFolderPath(暗示绝对)和RelativeFilePath可以组合以给出FilePath(暗示绝对)。

    此外,其中一些相关;例如,FilenameWithoutExtension是一种Filename,因此应该可转换。 FolderNameRelativeFolderPath,因此应该可转换。等。


    2

    对于简单的项目,您可以采用简单的答案: 没有使用“路径”这个词,因为如果与URL /路径一起工作,将其与Web路径区分开来会很有用。

    | name       | example          |
    |------------|------------------|
    | file       | /foo/bar/baa.txt |
    | filename   | baa.txt          |
    | stem       | baa              |
    | suffix     | .txt             |
    | ext        | txt              |
    | dir        | /foo/bar/        |
    | dirname    | bar              |
    | parent     | /foo/bar/        |
    | parentname | bar              |
    

    1
    我建议去除目录前面的斜杠,以便它们可以被追加。 - a2k42

    0
    路径组件的命名标准是什么?
    无论是什么,你最终会使用最适合你的方式。这是我的方法。
    A: "foo"
    filename, fn
    B: "foo.src"
    • 文件, f

    C: "src"
    extension_name, ext_name, xn
    D: ".src"
    • 扩展名extfx

    E: "C:\Users\OddThinking\Documents\My Source"
    • 基础目录基础文件夹BD

    F: "Widget\foo.src"
    - 相对路径:[relative_]filepath,[rel_]filepath,[rel_]fp
    G: "Widget"
    - [relative_]子目录, [rel_]子目, [rel_]sd
    H: "C:\Users\OddThinking\Documents\My Source\Widget"
    • [绝对路径_]子目录,[绝对路径_]子文件夹,[绝对路径_]子文件夹

    我:"C:\Users\OddThinking\Documents\My Source\Widget\foo.src"
    • [绝对路径]文件路径,[绝对]文件路径,[绝对]fp

    例子:

    f = fn + fx
    file = filename + ext
    file = filename + extension
    
    f = fn + "." + xn
    file = filename + "." + ext_name
    file = filename + "." + extension_name
    
    [abs_]fp = bd + [rel_]fp
    [abs_]filepath = basedir + [rel_]filepath
    [absolute_]filepath = basedirectory + [relative_]filepath
    
    [abs_]fp = bd + [rel_]sd + f
    [abs_]filepath = basedir + [rel_]subdir + file
    [absolute_]filepath = basedirectory + [relative_]subdirectory + file
    
    [abs_]fp = [abs_]sd + f
    [abs_]filepath = [abs_]subdir + file
    [absolute_]filepath = [absolute_]subdirectory + file
    

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