"pathlib" --- 物件導向檔案系統路徑
**********************************

在 3.4 版被加入.

**原始碼：**Lib/pathlib.py

======================================================================

此模組提供代表檔案系統路徑的類別，能適用不同作業系統的語意。路徑類別分
成兩種，一種是純路徑 (pure paths)，提供沒有 I/O 的單純計算操作，另一種
是實體路徑 (concrete paths)，繼承自純路徑但也提供 IO 操作。

[圖片：Inheritance diagram showing the classes available in pathlib.
The most basic class is PurePath, which has three direct subclasses:
PurePosixPath, PureWindowsPath, and Path. Further to these four
classes, there are two classes that use multiple inheritance:
PosixPath subclasses PurePosixPath and Path, and WindowsPath
subclasses PureWindowsPath and Path.][圖片]

如果你之前從未使用過此模組或不確定哪個類別適合你的任務，那你需要的最有
可能是 "Path"。它針對程式執行所在的平台實例化一個實體路徑。

純路徑在某些特殊情境下是有用的，例如：

1. 如果你想在 Unix 機器上處理 Windows 路徑（或反過來），你無法在 Unix
   上實例化 "WindowsPath"，但你可以實例化 "PureWindowsPath"。

2. 你想確保你的程式在操作路徑的時候不會真的存取到 OS。在這個情況下，實
   例化其中一種純路徑類別可能是有用的，因為它們不會有任何存取 OS 的操
   作。

也參考: **PEP 428**：pathlib 模組 -- 物件導向檔案系統路徑。

也參考: 針對字串上的底層路徑操作，你也可以使用 "os.path" 模組。


基本用法
========

匯入主要類別：

   >>> from pathlib import Path

列出子目錄：

   >>> p = Path('.')
   >>> [x for x in p.iterdir() if x.is_dir()]
   [PosixPath('.hg'), PosixPath('docs'), PosixPath('dist'),
    PosixPath('__pycache__'), PosixPath('build')]

在當前目錄樹下列出 Python 原始碼檔案：

   >>> list(p.glob('**/*.py'))
   [PosixPath('test_pathlib.py'), PosixPath('setup.py'),
    PosixPath('pathlib.py'), PosixPath('docs/conf.py'),
    PosixPath('build/lib/pathlib.py')]

瀏覽目錄樹內部：

   >>> p = Path('/etc')
   >>> q = p / 'init.d' / 'reboot'
   >>> q
   PosixPath('/etc/init.d/reboot')
   >>> q.resolve()
   PosixPath('/etc/rc.d/init.d/halt')

查詢路徑屬性：

   >>> q.exists()
   True
   >>> q.is_dir()
   False

開啟檔案：

   >>> with q.open() as f: f.readline()
   ...
   '#!/bin/bash\n'


純路徑
======

純路徑物件提供處理路徑的操作，實際上不會存取檔案系統。有三種方式可以存
取這些類別，我們也稱之為*類型 (flavours)*：

class pathlib.PurePath(*pathsegments)

   一個通用的類別，表示系統的路徑類型（實例化時會建立一個
   "PurePosixPath" 或 "PureWindowsPath")：

      >>> PurePath('setup.py')      # Running on a Unix machine
      PurePosixPath('setup.py')

   *pathsegments* 中的每個元素可以是以下的其中一種：一個表示路徑片段的
   字串，或一個物件，它實作了 "os.PathLike" 介面且其中的
   "__fspath__()" 方法會回傳字串，就像是另一個路徑物件：

      >>> PurePath('foo', 'some/path', 'bar')
      PurePosixPath('foo/some/path/bar')
      >>> PurePath(Path('foo'), Path('bar'))
      PurePosixPath('foo/bar')

   當沒有給 *pathsegments* 的時候，會假設是目前的目錄：

      >>> PurePath()
      PurePosixPath('.')

   如果一個片段是絕對路徑，則所有之前的片段會被忽略（類似
   "os.path.join()")：

      >>> PurePath('/etc', '/usr', 'lib64')
      PurePosixPath('/usr/lib64')
      >>> PureWindowsPath('c:/Windows', 'd:bar')
      PureWindowsPath('d:bar')

   在 Windows 系統上，當遇到具有根目錄的相對路徑片段（例如 "r'\foo'"）
   時，磁碟機 (drive) 部分不會被重置：

      >>> PureWindowsPath('c:/Windows', '/Program Files')
      PureWindowsPath('c:/Program Files')

   不必要的斜線和單點會被合併，但雙點 ("'..'") 和前置的雙斜線 ("'//'")
   不會被合併，因為這樣會因為各種原因改變路徑的意義（例如符號連結
   (symbolic links)、UNC 路徑）：

      >>> PurePath('foo//bar')
      PurePosixPath('foo/bar')
      >>> PurePath('//foo/bar')
      PurePosixPath('//foo/bar')
      >>> PurePath('foo/./bar')
      PurePosixPath('foo/bar')
      >>> PurePath('foo/../bar')
      PurePosixPath('foo/../bar')

   （一個使得 "PurePosixPath('foo/../bar')" 等同於
   "PurePosixPath('bar')" 的單純方法，但如果 "foo" 是指到另一個目錄的
   符號連結，就會是錯誤的。）

   純路徑物件實作了 "os.PathLike" 介面，使得它們可以在任何接受該介面的
   地方使用。

   在 3.6 版的變更: 新增了對於 "os.PathLike" 介面的支援。

class pathlib.PurePosixPath(*pathsegments)

   "PurePath" 的一個子類別，該路徑類型表示非 Windows 檔案系統的路徑：

      >>> PurePosixPath('/etc')
      PurePosixPath('/etc')

   *pathsegments* 的指定方式與 "PurePath" 類似。

class pathlib.PureWindowsPath(*pathsegments)

   "PurePath" 的一個子類別，該路徑類型表示 Windows 檔案系統的路徑，包
   括  UNC paths：

      >>> PureWindowsPath('c:/Program Files/')
      PureWindowsPath('c:/Program Files')
      >>> PureWindowsPath('//server/share/file')
      PureWindowsPath('//server/share/file')

   *pathsegments* 的指定方式與 "PurePath" 類似。

不論你使用的是什麼系統，你都可以實例化這些類別，因為它們不提供任何涉及
系統呼叫的操作。


通用屬性
--------

路徑物件是不可變 (immutable) 且可雜湊 (*hashable*) 的。相同類型的路徑
物件可以被比較和排序。這些屬性遵守該類型的大小寫語意規則：

   >>> PurePosixPath('foo') == PurePosixPath('FOO')
   False
   >>> PureWindowsPath('foo') == PureWindowsPath('FOO')
   True
   >>> PureWindowsPath('FOO') in { PureWindowsPath('foo') }
   True
   >>> PureWindowsPath('C:') < PureWindowsPath('d:')
   True

不同類型的路徑物件在比較時視為不相等且無法被排序：

   >>> PureWindowsPath('foo') == PurePosixPath('foo')
   False
   >>> PureWindowsPath('foo') < PurePosixPath('foo')
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: '<' not supported between instances of 'PureWindowsPath' and 'PurePosixPath'


運算子
------

斜線運算子 (slash operator) 用於建立子路徑，就像是 "os.path.join()" 函
式一樣。如果引數是絕對路徑，則忽略前一個路徑。在 Windows 系統上，當引
數是具有根目錄的相對路徑（例如，"r'\foo'"），磁碟機部分不會被重置：

   >>> p = PurePath('/etc')
   >>> p
   PurePosixPath('/etc')
   >>> p / 'init.d' / 'apache2'
   PurePosixPath('/etc/init.d/apache2')
   >>> q = PurePath('bin')
   >>> '/usr' / q
   PurePosixPath('/usr/bin')
   >>> p / '/an_absolute_path'
   PurePosixPath('/an_absolute_path')
   >>> PureWindowsPath('c:/Windows', '/Program Files')
   PureWindowsPath('c:/Program Files')

路徑物件可以被用在任何可以接受實作 "os.PathLike" 的物件的地方：

   >>> import os
   >>> p = PurePath('/etc')
   >>> os.fspath(p)
   '/etc'

路徑的字串表示是原始的檔案系統路徑本身（以原生的形式，例如在 Windows
下是反斜線），你可以將其傳入任何將檔案路徑當作字串傳入的函式：

   >>> p = PurePath('/etc')
   >>> str(p)
   '/etc'
   >>> p = PureWindowsPath('c:/Program Files')
   >>> str(p)
   'c:\\Program Files'

類似地，對路徑呼叫 "bytes" 會得到原始檔案系統路徑的 bytes 物件，就像使
用 "os.fsencode()" 編碼過的一樣：

   >>> bytes(p)
   b'/etc'

備註:

  只建議在 Unix 下呼叫 "bytes"。在 Windows 裡，unicode 形式是檔案系統
  路徑的權威表示方式。


對個別組成的存取
----------------

可以使用下列屬性來存取路徑的個別「組成」(parts, components)：

PurePath.parts

   一個可存取路徑的各組成的元組：

      >>> p = PurePath('/usr/bin/python3')
      >>> p.parts
      ('/', 'usr', 'bin', 'python3')

      >>> p = PureWindowsPath('c:/Program Files/PSF')
      >>> p.parts
      ('c:\\', 'Program Files', 'PSF')

   （特別注意磁碟機跟本地根目錄是如何被重新組合成一個單一組成）


方法與屬性
----------

純路徑提供以下方法與屬性：

PurePath.drive

   若存在則為一個表示磁碟機字母 (drive letter) 或磁碟機名稱 (drive
   name) 的字串：

      >>> PureWindowsPath('c:/Program Files/').drive
      'c:'
      >>> PureWindowsPath('/Program Files/').drive
      ''
      >>> PurePosixPath('/etc').drive
      ''

   UNC shares 也被視為磁碟機：

      >>> PureWindowsPath('//host/share/foo.txt').drive
      '\\\\host\\share'

PurePath.root

   若存在則為一個表示（本地或全域）根目錄的字串：

      >>> PureWindowsPath('c:/Program Files/').root
      '\\'
      >>> PureWindowsPath('c:Program Files/').root
      ''
      >>> PurePosixPath('/etc').root
      '/'

   UNC shares 都會有一個根目錄：

      >>> PureWindowsPath('//host/share').root
      '\\'

   如果路徑以超過兩個連續的斜線開頭，"PurePosixPath" 會合併它們：

      >>> PurePosixPath('//etc').root
      '//'
      >>> PurePosixPath('///etc').root
      '/'
      >>> PurePosixPath('////etc').root
      '/'

   備註:

     此行為符合 *The Open Group Base Specifications Issue 6*，章節
     4.11 路徑名稱解析：*「以兩個連續斜線開頭的路徑名稱可以根據實作定
     義的方式來解讀，儘管如此，開頭超過兩個斜線應該視為單一斜線。」*

PurePath.anchor

   磁碟機與根目錄的結合：

      >>> PureWindowsPath('c:/Program Files/').anchor
      'c:\\'
      >>> PureWindowsPath('c:Program Files/').anchor
      'c:'
      >>> PurePosixPath('/etc').anchor
      '/'
      >>> PureWindowsPath('//host/share').anchor
      '\\\\host\\share\\'

PurePath.parents

   一個不可變的序列，為路徑邏輯上的祖先 (logical ancestors) 提供存取：

      >>> p = PureWindowsPath('c:/foo/bar/setup.py')
      >>> p.parents[0]
      PureWindowsPath('c:/foo/bar')
      >>> p.parents[1]
      PureWindowsPath('c:/foo')
      >>> p.parents[2]
      PureWindowsPath('c:/')

   在 3.10 版的變更: 父序列現在支援 *slices* 及負的索引值。

PurePath.parent

   邏輯上的父路徑：

      >>> p = PurePosixPath('/a/b/c/d')
      >>> p.parent
      PurePosixPath('/a/b/c')

   你不能越過一個 anchor 或空路徑：

      >>> p = PurePosixPath('/')
      >>> p.parent
      PurePosixPath('/')
      >>> p = PurePosixPath('.')
      >>> p.parent
      PurePosixPath('.')

   備註:

     這是一個純粹字句上的 (lexical) 運算，因此會有以下行為：

        >>> p = PurePosixPath('foo/..')
        >>> p.parent
        PurePosixPath('foo')

     如果你想要沿任意的檔案系統路徑往上走，建議要先呼叫
     "Path.resolve()" 來解析符號連結 (symlink) 及去除其中的 "”..”"。

PurePath.name

   最後的路徑組成 (final path component) 的字串表示，不包含任何磁碟機
   或根目錄：

      >>> PurePosixPath('my/library/setup.py').name
      'setup.py'

   UNC 磁碟機名稱並沒有算在內：

      >>> PureWindowsPath('//some/share/setup.py').name
      'setup.py'
      >>> PureWindowsPath('//some/share').name
      ''

PurePath.suffix

   若存在則為最後的路徑組成的檔案副檔名：

      >>> PurePosixPath('my/library/setup.py').suffix
      '.py'
      >>> PurePosixPath('my/library.tar.gz').suffix
      '.gz'
      >>> PurePosixPath('my/library').suffix
      ''

PurePath.suffixes

   路徑檔案副檔名的串列：

      >>> PurePosixPath('my/library.tar.gar').suffixes
      ['.tar', '.gar']
      >>> PurePosixPath('my/library.tar.gz').suffixes
      ['.tar', '.gz']
      >>> PurePosixPath('my/library').suffixes
      []

PurePath.stem

   最後的路徑組成，不包括後綴 (suffix)：

      >>> PurePosixPath('my/library.tar.gz').stem
      'library.tar'
      >>> PurePosixPath('my/library.tar').stem
      'library'
      >>> PurePosixPath('my/library').stem
      'library'

PurePath.as_posix()

   回傳一個使用正斜線 ("/") 的路徑的字串表示：

      >>> p = PureWindowsPath('c:\\windows')
      >>> str(p)
      'c:\\windows'
      >>> p.as_posix()
      'c:/windows'

PurePath.as_uri()

   以 "file" URI 來表示一個路徑。如果不是絕對路徑會引發 "ValueError"。

   >>> p = PurePosixPath('/etc/passwd')
   >>> p.as_uri()
   'file:///etc/passwd'
   >>> p = PureWindowsPath('c:/Windows')
   >>> p.as_uri()
   'file:///c:/Windows'

PurePath.is_absolute()

   回傳一個路徑是否是絕對路徑。一個路徑被視為絕對路徑的條件是它同時有
   根目錄及（如果該系統類型允許的話）磁碟機：

      >>> PurePosixPath('/a/b').is_absolute()
      True
      >>> PurePosixPath('a/b').is_absolute()
      False

      >>> PureWindowsPath('c:/a/b').is_absolute()
      True
      >>> PureWindowsPath('/a/b').is_absolute()
      False
      >>> PureWindowsPath('c:').is_absolute()
      False
      >>> PureWindowsPath('//some/share').is_absolute()
      True

PurePath.is_relative_to(other)

   回傳此路徑是否為 *other* 路徑的相對路徑。

   >>> p = PurePath('/etc/passwd')
   >>> p.is_relative_to('/etc')
   True
   >>> p.is_relative_to('/usr')
   False

   該方法是基於字串的；它既不存取檔案系統，也不特別處理 "".."" 片段。
   以下程式碼是等效的：

   >>> u = PurePath('/usr')
   >>> u == p or u in p.parents
   False

   在 3.9 版被加入.

   Deprecated since version 3.12, will be removed in version 3.14: 額
   外引數的傳入已棄用；如果有的話，它們會與 *other* 連接在一起。

PurePath.is_reserved()

   對 "PureWindowsPath" 來說，當路徑在 Windows 下被視為保留的話會回傳
   "True"，否則回傳 "False"。對 "PurePosixPath" 來說，總是回傳 "False"
   。

   >>> PureWindowsPath('nul').is_reserved()
   True
   >>> PurePosixPath('nul').is_reserved()
   False

   在保留路徑上的檔案系統呼叫會神秘地失敗或有意外的效果。

PurePath.joinpath(*pathsegments)

   呼叫此方法會依序結合每個所給定的 *pathsegments* 到路徑上：

      >>> PurePosixPath('/etc').joinpath('passwd')
      PurePosixPath('/etc/passwd')
      >>> PurePosixPath('/etc').joinpath(PurePosixPath('passwd'))
      PurePosixPath('/etc/passwd')
      >>> PurePosixPath('/etc').joinpath('init.d', 'apache2')
      PurePosixPath('/etc/init.d/apache2')
      >>> PureWindowsPath('c:').joinpath('/Program Files')
      PureWindowsPath('c:/Program Files')

PurePath.match(pattern, *, case_sensitive=None)

   將路徑與 glob 形式的樣式 (glob-style pattern) 做比對。如果比對成功
   則回傳 "True"，否則回傳 "False"。

   如果 *pattern* 是相對的，則路徑可以是相對或絕對的，而且會從右邊來完
   成比對：

      >>> PurePath('a/b.py').match('*.py')
      True
      >>> PurePath('/a/b/c.py').match('b/*.py')
      True
      >>> PurePath('/a/b/c.py').match('a/*.py')
      False

   如果 *pattern* 是絕對的，則路徑必須是絕對的，且整個路徑都要比對到：

      >>> PurePath('/a.py').match('/*.py')
      True
      >>> PurePath('a/b.py').match('/*.py')
      False

   *pattern* 可以是另一個路徑物件；這會加速對多個檔案比對相同的樣式：

      >>> pattern = PurePath('*.py')
      >>> PurePath('a/b.py').match(pattern)
      True

   備註:

     The recursive wildcard ""**"" isn't supported by this method (it
     acts like non-recursive ""*"".)

   在 3.12 版的變更: 接受一個有實作 "os.PathLike" 介面的物件。

   像其它方法一樣，是否區分大小寫會遵循平台的預設行為：

      >>> PurePosixPath('b.py').match('*.PY')
      False
      >>> PureWindowsPath('b.py').match('*.PY')
      True

   將 *case_sensitive* 設定成 "True" 或 "False" 會覆蓋這個行為。

   在 3.12 版的變更: 新增 *case_sensitive* 參數。

PurePath.relative_to(other, walk_up=False)

   計算這個路徑相對於 *other* 所表示路徑的版本。如果做不到會引發
   "ValueError"：

      >>> p = PurePosixPath('/etc/passwd')
      >>> p.relative_to('/')
      PurePosixPath('etc/passwd')
      >>> p.relative_to('/etc')
      PurePosixPath('passwd')
      >>> p.relative_to('/usr')
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "pathlib.py", line 941, in relative_to
          raise ValueError(error_message.format(str(self), str(formatted)))
      ValueError: '/etc/passwd' is not in the subpath of '/usr' OR one path is relative and the other is absolute.

   當 *walk_up* 是 False（預設值），路徑必須以 *other* 為開始。當此引
   數是 True，可能會加入 ".." 以組成相對路徑。在其他情況下，例如路徑參
   考到不同的磁碟機，則會引發 "ValueError"：

      >>> p.relative_to('/usr', walk_up=True)
      PurePosixPath('../etc/passwd')
      >>> p.relative_to('foo', walk_up=True)
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "pathlib.py", line 941, in relative_to
          raise ValueError(error_message.format(str(self), str(formatted)))
      ValueError: '/etc/passwd' is not on the same drive as 'foo' OR one path is relative and the other is absolute.

   警告:

     這個函式是 "PurePath" 的一部分且可以在字串上運作。它不會檢查或存
     取實際的檔案架構。這會影響到 *walk_up* 選項，因為它假設路徑中沒有
     符號連結；如果需要解析符號連結的話可以先呼叫 "resolve()"。

   在 3.12 版的變更: 加入 *walk_up* 參數（舊的行為和 "walk_up=False"
   相同）。

   Deprecated since version 3.12, will be removed in version 3.14: 額
   外位置引數的傳入已棄用；如果有的話，它們會與 *other* 連接在一起。

PurePath.with_name(name)

   回傳一個修改 "name" 後的新路徑。如果原始路徑沒有名稱則引發
   ValueError：

      >>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz')
      >>> p.with_name('setup.py')
      PureWindowsPath('c:/Downloads/setup.py')
      >>> p = PureWindowsPath('c:/')
      >>> p.with_name('setup.py')
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "/home/antoine/cpython/default/Lib/pathlib.py", line 751, in with_name
          raise ValueError("%r has an empty name" % (self,))
      ValueError: PureWindowsPath('c:/') has an empty name

PurePath.with_stem(stem)

   回傳一個修改 "stem" 後的新路徑。如果原始路徑沒有名稱則引發
   ValueError：

      >>> p = PureWindowsPath('c:/Downloads/draft.txt')
      >>> p.with_stem('final')
      PureWindowsPath('c:/Downloads/final.txt')
      >>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz')
      >>> p.with_stem('lib')
      PureWindowsPath('c:/Downloads/lib.gz')
      >>> p = PureWindowsPath('c:/')
      >>> p.with_stem('')
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "/home/antoine/cpython/default/Lib/pathlib.py", line 861, in with_stem
          return self.with_name(stem + self.suffix)
        File "/home/antoine/cpython/default/Lib/pathlib.py", line 851, in with_name
          raise ValueError("%r has an empty name" % (self,))
      ValueError: PureWindowsPath('c:/') has an empty name

   在 3.9 版被加入.

PurePath.with_suffix(suffix)

   回傳一個修改 "suffix" 後的新路徑。如果原始路徑沒有後綴，新的
   *suffix* 會附加在後面。如果 *suffix* 是一個空字串，原來的後綴會被移
   除：

      >>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz')
      >>> p.with_suffix('.bz2')
      PureWindowsPath('c:/Downloads/pathlib.tar.bz2')
      >>> p = PureWindowsPath('README')
      >>> p.with_suffix('.txt')
      PureWindowsPath('README.txt')
      >>> p = PureWindowsPath('README.txt')
      >>> p.with_suffix('')
      PureWindowsPath('README')

PurePath.with_segments(*pathsegments)

   透過結合給定的 *pathsegments* 建立一個相同類型的新路徑物件，當一個
   衍生路徑被建立的時候會呼叫這個方法，例如從 "parent" 和
   "relative_to()" 建立衍生路徑。子類別可以覆寫此方法來傳遞資訊給衍生
   路徑，例如：

      from pathlib import PurePosixPath

      class MyPath(PurePosixPath):
          def __init__(self, *pathsegments, session_id):
              super().__init__(*pathsegments)
              self.session_id = session_id

          def with_segments(self, *pathsegments):
              return type(self)(*pathsegments, session_id=self.session_id)

      etc = MyPath('/etc', session_id=42)
      hosts = etc / 'hosts'
      print(hosts.session_id)  # 42

   在 3.12 版被加入.


實體路徑
========

實體路徑是純路徑類別的子類別。除了後者本來就有提供的操作，它們也提供方
法可以對路徑物件做系統呼叫。有三種方式可以實例化實體路徑：

class pathlib.Path(*pathsegments)

   "PurePath" 的子類別，此類別表示系統的路徑類型的實體路徑（實例化時會
   建立一個 "PosixPath" 或 "WindowsPath"）：

      >>> Path('setup.py')
      PosixPath('setup.py')

   *pathsegments* 的指定方式與 "PurePath" 類似。

class pathlib.PosixPath(*pathsegments)

   "Path" 和 "PurePosixPath" 的子類別，此類別表示實體非 Windows 檔案系
   統路徑：

      >>> PosixPath('/etc')
      PosixPath('/etc')

   *pathsegments* 的指定方式與 "PurePath" 類似。

class pathlib.WindowsPath(*pathsegments)

   "Path" 和 "PureWindowsPath" 的子類別，此類別表示實體 Windows 檔案系
   統路徑：

      >>> WindowsPath('c:/Program Files/')
      WindowsPath('c:/Program Files')

   *pathsegments* 的指定方式與 "PurePath" 類似。

你只能實例化對應你的系統的類別類型（允許在不相容的路徑類型上做系統呼叫
可能在你的應用程式導致漏洞或故障）：

   >>> import os
   >>> os.name
   'posix'
   >>> Path('setup.py')
   PosixPath('setup.py')
   >>> PosixPath('setup.py')
   PosixPath('setup.py')
   >>> WindowsPath('setup.py')
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
     File "pathlib.py", line 798, in __new__
       % (cls.__name__,))
   NotImplementedError: cannot instantiate 'WindowsPath' on your system

有些實體路徑方法會在系統呼叫失敗（例如因為路徑不存在）時引發 "OSError"


Expanding and resolving paths
-----------------------------

classmethod Path.home()

   回傳一個代表使用者家目錄的新的路徑物件（像以 "~" 構成的
   "os.path.expanduser()" 的回傳一樣）。如果無法解析家目錄，會引發
   "RuntimeError"。

      >>> Path.home()
      PosixPath('/home/antoine')

   在 3.5 版被加入.

Path.expanduser()

   回傳一個展開 "~" 和 "~user" 構成的新路徑，像 "os.path.expanduser()"
   回傳的一樣。如果無法解析家目錄，會引發 "RuntimeError"。

      >>> p = PosixPath('~/films/Monty Python')
      >>> p.expanduser()
      PosixPath('/home/eric/films/Monty Python')

   在 3.5 版被加入.

classmethod Path.cwd()

   回傳一個代表目前目錄的新的路徑物件（像 "os.getcwd()" 回傳的一樣）：

      >>> Path.cwd()
      PosixPath('/home/antoine/pathlib')

Path.absolute()

   將路徑轉換為絕對路徑，不進行標準化或解析符號連結。回傳一個新的路徑
   物件：

      >>> p = Path('tests')
      >>> p
      PosixPath('tests')
      >>> p.absolute()
      PosixPath('/home/antoine/pathlib/tests')

Path.resolve(strict=False)

   將路徑轉換為絕對路徑，解析所有符號連結。回傳一個新的路徑物件：

      >>> p = Path()
      >>> p
      PosixPath('.')
      >>> p.resolve()
      PosixPath('/home/antoine/pathlib')

   同時也會消除 "".."" 的路徑組成（只有此方法這樣做）：

      >>> p = Path('docs/../setup.py')
      >>> p.resolve()
      PosixPath('/home/antoine/pathlib/setup.py')

   如果路徑不存在且 *strict* 為 "True"，則引發 "FileNotFoundError"。如
   果 *strict* 為 "False"，則將盡可能解析該路徑，並將任何剩餘部分追加
   到路徑中，而不檢查其是否存在。如果在解析過程中遇到無窮迴圈，則引發
   "RuntimeError"。

   在 3.6 版的變更: 新增 *strict* 參數（在 3.6 版本之前的行為是嚴格的
   ）。

Path.readlink()

   回傳符號連結指向的路徑（如 "os.readlink()" 的回傳值）：

      >>> p = Path('mylink')
      >>> p.symlink_to('setup.py')
      >>> p.readlink()
      PosixPath('setup.py')

   在 3.9 版被加入.


Querying file type and status
-----------------------------

在 3.8 版的變更: "exists()"、"is_dir()"、"is_file()"、"is_mount()"、
"is_symlink()"、"is_block_device()"、"is_char_device()"、"is_fifo()"、
"is_socket()" 遇到路徑包含 OS 層無法表示的字元時現在會回傳 "False" 而
不是引發例外。

Path.stat(*, follow_symlinks=True)

   Return an "os.stat_result" object containing information about this
   path, like "os.stat()". The result is looked up at each call to
   this method.

   此方法通常會跟隨 (follow) 符號連結；想要取得符號連結的資訊，可以加
   上引數 "follow_symlinks=False" 或使用 "lstat()"。

      >>> p = Path('setup.py')
      >>> p.stat().st_size
      956
      >>> p.stat().st_mtime
      1327883547.852554

   在 3.10 版的變更: 新增 *follow_symlinks* 參數。

Path.lstat()

   類似 "Path.stat()"，但如果該路徑指向一個符號連結，則回傳符號連結的
   資訊而不是其指向的目標。

Path.exists(*, follow_symlinks=True)

   如果路徑指向存在的檔案或目錄則回傳 "True"。

   此方法通常會跟隨符號連結；如果想檢查符號連結是否存在，可以加上引數
   "follow_symlinks=False"。

      >>> Path('.').exists()
      True
      >>> Path('setup.py').exists()
      True
      >>> Path('/etc').exists()
      True
      >>> Path('nonexistentfile').exists()
      False

   在 3.12 版的變更: 新增 *follow_symlinks* 參數。

Path.is_file()

   如果該路徑指向一個普通檔案（或者是一個指向普通檔案的符號連結）則回
   傳 "True"，如果指向其他類型的檔案則回傳 "False"。

   如果路徑不存在或者是一個斷掉的符號連結則也會回傳 "False"；其他錯誤
   （例如權限錯誤）則會傳遞出來。

Path.is_dir()

   如果該路徑指向一個目錄（或者是一個指向目錄的符號連結）則回傳 "True"
   ，如果指向其他類型的檔案則回傳 "False"。

   如果路徑不存在或者是一個斷掉的符號連結則也會回傳 "False"；其他錯誤
   （例如權限錯誤）則會傳遞出來。

Path.is_symlink()

   如果該路徑指向一個符號連結則回傳 "True"，否則回傳 "False"。

   如果該路徑不存在也會回傳 "False"；其他錯誤（例如權限錯誤）則會傳遞
   出來。

Path.is_junction()

   如果該路徑指向一個連接點 (junction) 則回傳 "True"，對其他類型的檔案
   則回傳 "False"。目前只有 Windows 支援連接點。

   在 3.12 版被加入.

Path.is_mount()

   如果路徑是一個 *mount point*（一個檔案系統裡掛載不同檔案系統的存取
   點）則回傳 "True"。在 POSIX 上，此函式檢查 *path* 的父路徑
   "path/.." 是否和 *path* 在不同的裝置上，或者 "path/.." 和 *path* 是
   否指向相同裝置的相同 i-node ── 這對於所有 Unix 和 POSIX 變體來說應
   該會偵測出掛載點。在 Windows 上，一個掛載點被視為一個根磁碟機字母（
   例如 "c:\"）、一個 UNC share（例如 "\\server\share"）或是掛載的檔案
   系統目錄。

   在 3.7 版被加入.

   在 3.12 版的變更: 加入對 Windows 的支援。

Path.is_socket()

   如果該路徑指向一個 Unix socket（或者是一個指向 Unix socket 的符號連
   結）則會回傳 "True"，如果指向其他類型的檔案則回傳 "False"。

   如果路徑不存在或者是一個斷掉的符號連結則也會回傳 "False"；其他錯誤
   （例如權限錯誤）則會傳遞出來。

Path.is_fifo()

   如果該路徑指向一個 FIFO（或者是一個指向 FIFO 的符號連結）則會回傳
   "True"，如果指向其他類型的檔案則回傳 "False"。

   如果路徑不存在或者是一個斷掉的符號連結則也會回傳 "False"；其他錯誤
   （例如權限錯誤）則會傳遞出來。

Path.is_block_device()

   如果該路徑指向一個區塊裝置 (block device)（或者是一個指向區塊裝置的
   符號連結）則會回傳 "True"，如果指向其他類型的檔案則回傳 "False"。

   如果路徑不存在或者是一個斷掉的符號連結則也會回傳 "False"；其他錯誤
   （例如權限錯誤）則會傳遞出來。

Path.is_char_device()

   如果該路徑指向一個字元裝置 (character device)（或者是一個指向字元裝
   置的符號連結）則會回傳 "True"，如果指向其他類型的檔案則回傳 "False"
   。

   如果路徑不存在或者是一個斷掉的符號連結則也會回傳 "False"；其他錯誤
   （例如權限錯誤）則會傳遞出來。

Path.samefile(other_path)

   回傳此路徑是否指向與 *other_path* 相同的檔案，*other_path* 可以是路
   徑 (Path) 物件或字串。其語義類似於 "os.path.samefile()" 和
   "os.path.samestat()"。

   若任何一個檔案因為某些原因無法存取，則引發 "OSError"。

      >>> p = Path('spam')
      >>> q = Path('eggs')
      >>> p.samefile(q)
      False
      >>> p.samefile('spam')
      True

   在 3.5 版被加入.


Reading and writing files
-------------------------

Path.open(mode='r', buffering=-1, encoding=None, errors=None, newline=None)

   開啟該路徑指向的檔案，像內建的 "open()" 函式做的一樣：

      >>> p = Path('setup.py')
      >>> with p.open() as f:
      ...     f.readline()
      ...
      '#!/usr/bin/env python3\n'

Path.read_text(encoding=None, errors=None)

   將路徑指向的檔案的解碼內容以字串形式回傳：

      >>> p = Path('my_text_file')
      >>> p.write_text('Text file contents')
      18
      >>> p.read_text()
      'Text file contents'

   該檔案被打開並且隨後關閉。可選參數的含義與 "open()" 中的相同。

   在 3.5 版被加入.

Path.read_bytes()

   將路徑指向的檔案的二進位內容以一個位元組物件回傳：

      >>> p = Path('my_binary_file')
      >>> p.write_bytes(b'Binary file contents')
      20
      >>> p.read_bytes()
      b'Binary file contents'

   在 3.5 版被加入.

Path.write_text(data, encoding=None, errors=None, newline=None)

   以文字模式開啟指向的檔案，將 *data* 寫到檔案，並關閉檔案:: ：

      >>> p = Path('my_text_file')
      >>> p.write_text('Text file contents')
      18
      >>> p.read_text()
      'Text file contents'

   一個名稱相同的已存在檔案會被覆寫。可選參數和 "open()" 的參數有相同
   意義。

   在 3.5 版被加入.

   在 3.10 版的變更: 新增 *newline* 參數。

Path.write_bytes(data)

   以位元組模式開啟指向的檔案，將 *data* 寫到檔案，並關閉檔案:: ：

      >>> p = Path('my_binary_file')
      >>> p.write_bytes(b'Binary file contents')
      20
      >>> p.read_bytes()
      b'Binary file contents'

   一個名稱相同的已存在檔案會被覆寫。

   在 3.5 版被加入.


讀取目錄
--------

Path.iterdir()

   當該路徑指向一個目錄，會 yield 目錄裡面的路徑物件：

      >>> p = Path('docs')
      >>> for child in p.iterdir(): child
      ...
      PosixPath('docs/conf.py')
      PosixPath('docs/_templates')
      PosixPath('docs/make.bat')
      PosixPath('docs/index.rst')
      PosixPath('docs/_build')
      PosixPath('docs/_static')
      PosixPath('docs/Makefile')

   子路徑會以任意順序被 yield，且不會包含特殊項目 "'.'" 和 "'..'"。如
   果一個檔案在建立這個疊代器之後加到該目錄或從目錄刪除，這個檔案的路
   徑物件是否會被包含是沒有明定的。

   If the path is not a directory or otherwise inaccessible, "OSError"
   is raised.

Path.glob(pattern, *, case_sensitive=None)

   在該路徑表示的目錄裡，以 glob 方式比對所給定的相對 *pattern*，並
   yield 所有比對到的檔案（任意類型）：

      >>> sorted(Path('.').glob('*.py'))
      [PosixPath('pathlib.py'), PosixPath('setup.py'), PosixPath('test_pathlib.py')]
      >>> sorted(Path('.').glob('*/*.py'))
      [PosixPath('docs/conf.py')]

   模式 (pattern) 和給 "fnmatch" 的一樣，加上 ""**"" 代表「目前目錄及
   所有遞迴的子目錄」。也就是說它能夠做遞迴的 glob 比對：

      >>> sorted(Path('.').glob('**/*.py'))
      [PosixPath('build/lib/pathlib.py'),
       PosixPath('docs/conf.py'),
       PosixPath('pathlib.py'),
       PosixPath('setup.py'),
       PosixPath('test_pathlib.py')]

   此方法在頂層目錄上呼叫 "Path.is_dir()" 並傳遞引發的任何 "OSError"
   例外。將會抑制在目錄對於 "OSError" 例外的後續掃描。

   預設情況下，或者當 *case_sensitive* 僅限關鍵字引數被設定為 "None"
   的時候，此方法會使用平台特定的大小寫規則來比對路徑；通常在 POSIX 上
   會區分大小寫，而在 Windows 上不區分大小寫。將 *case_sensitive* 設成
   "True" 或 "False" 會覆寫這個行為。

   備註:

     在很大的目錄樹裡使用 ""**"" 可能會耗費過多的時間。

   Raises an auditing event "pathlib.Path.glob" with arguments "self",
   "pattern".

   在 3.11 版的變更: 如果 *pattern* 以路徑名稱組成的分隔符號（"sep" 或
   "altsep"）作結尾則只會回傳目錄。

   在 3.12 版的變更: 新增 *case_sensitive* 參數。

Path.rglob(pattern, *, case_sensitive=None)

   遞迴地 glob 給定的相對 *pattern*。這相當於在給定的相對 *pattern* 前
   面加上 ""**/"" 並呼叫 "Path.glob()"，其中 *patterns* 和給 "fnmatch"
   的相同：

      >>> sorted(Path().rglob("*.py"))
      [PosixPath('build/lib/pathlib.py'),
       PosixPath('docs/conf.py'),
       PosixPath('pathlib.py'),
       PosixPath('setup.py'),
       PosixPath('test_pathlib.py')]

   預設情況下，或者當 *case_sensitive* 僅限關鍵字引數被設定為 "None"
   的時候，此方法會使用平台特定的大小寫規則來比對路徑；通常在 POSIX 上
   會區分大小寫，而在 Windows 上不區分大小寫。將 *case_sensitive* 設成
   "True" 或 "False" 會覆寫這個行為。

   Raises an auditing event "pathlib.Path.rglob" with arguments
   "self", "pattern".

   在 3.11 版的變更: 如果 *pattern* 以路徑名稱組成的分隔符號（"sep" 或
   "altsep"）作結尾則只會回傳目錄。

   在 3.12 版的變更: 新增 *case_sensitive* 參數。

Path.walk(top_down=True, on_error=None, follow_symlinks=False)

   透過由上而下或由下而上地走訪目錄樹產生目錄樹裡的檔案名稱。

   對每個以 *self* 為根且在目錄樹裡的目錄（包含 *self* 但不包含 '.' 和
   '..' ），此方法會 yield 一個 "(dirpath, dirnames, filenames)" 的三
   元素元組。

   *dirpath* 是一個目前走訪到的目錄的 "Path"，*dirnames* 是一個
   *dirpath* 裡的子目錄名稱的字串串列（不包含 "'.'" 和 "'..'" ），而
   *filenames* 是一個 *dirpath* 裡非目錄檔案名稱的字串串列。要取得在
   *dirpath* 裡檔案或目錄的完整路徑（以 *self* 開頭），可以使用
   "dirpath / name"。會根據檔案系統來決定串列是否有排序。

   如果可選引數 *top_down* 是 true（預設值），一個目錄的三元素元組會在
   其任何子目錄的三元素元組之前產生（目錄是由上而下走訪）。如果
   *top_down* 是 false，一個目錄的三元素元組會在其所有子目錄的三元素元
   組之後產生（目錄是由下而上走訪）。不論 *top_down* 的值是什麼，子目
   錄的串列會在走訪該目錄及其子目錄的三元素元組之前取得。

   當 *top_down* 是 true，呼叫者可以原地 (in-place) 修改 *dirnames* 串
   列（例如使用 "del" 或切片賦值 (slice assignment)），且
   "Path.walk()" 只會遞迴進名稱依然留在 *dirnames* 裡的子目錄。這可以
   用來修剪搜尋，或者強加特定順序的訪問，或者甚至在繼續 "Path.walk()"
   之前，用來告訴 "Path.walk()" 關於呼叫者建立或重新命名的目錄。當
   *top_down* 是 false 的時候，修改 *dirnames* 對 "Path.walk()" 的行為
   沒有影響，因為 *dirnames* 裡的目錄已經在 *dirnames* yield 給呼叫者
   之前被產生。

   預設來自 "os.scandir()" 的錯誤會被忽略。如果指定了可選引數
   *on_error*（它應該要是一個可呼叫物件），它會被以一個 "OSError" 實例
   為引數來呼叫。這個可呼叫物件可以處理錯誤以繼續走訪，或者再次引發錯
   誤來停止走訪。注意，檔案名稱可以從例外物件的 "filename" 屬性來取得
   。

   預設 "Path.walk()" 不會跟隨符號連結，而是會把它們加到 *filenames*
   串列。將 *follow_symlinks* 設定為 true 會解析符號連結，並將它們根據
   其指向的目標放在適當的 *dirnames* 和 *filenames*，而因此訪問到符號
   連結指向的目錄（在有支援符號連結的地方）。

   備註:

     需要注意的是如果符號連結指向一個其本身的父目錄，則將
     *follow_symlinks* 設定為 true 會導致無窮的遞迴。"Path.walk()" 不
     會紀錄其已經訪問過的目錄。

   備註:

     "Path.walk()" 假設其走訪的目錄在執行過程中不會被修改。舉例來說，
     如果在 *dirnames* 裡的目錄已經被一個符號連結取代，且
     *follow_symlinks* 是 false，"Path.walk()" 依然會試著往下進入它。
     為了防止這樣的行為，可以從 *dirnames* 適當地移除目錄。

   備註:

     如果 *follow_symlinks* 是 false，和 "os.walk()" 行為不同的是
     "Path.walk()" 會將指向目錄的符號連結放在 *filenames* 串列。

   這個範例會顯示在每個目錄裡所有檔案使用的位元組數量，同時間忽略
   "__pycache__" 目錄：

      from pathlib import Path
      for root, dirs, files in Path("cpython/Lib/concurrent").walk(on_error=print):
        print(
            root,
            "consumes",
            sum((root / file).stat().st_size for file in files),
            "bytes in",
            len(files),
            "non-directory files"
        )
        if '__pycache__' in dirs:
              dirs.remove('__pycache__')

   下一個範例是 "shutil.rmtree()" 的一個簡單的實作方式。由下而上走訪目
   錄樹是必要的，因為 "rmdir()" 不允許在目錄為空之前刪除它：

      # Delete everything reachable from the directory "top".
      # CAUTION:  This is dangerous! For example, if top == Path('/'),
      # it could delete all of your files.
      for root, dirs, files in top.walk(top_down=False):
          for name in files:
              (root / name).unlink()
          for name in dirs:
              (root / name).rmdir()

   在 3.12 版被加入.


建立檔案與目錄
--------------

Path.touch(mode=0o666, exist_ok=True)

   根據給定路徑來建立一個檔案。如果 *mode* 有給定，它會與行程的
   "umask" 值結合，以確定檔案模式和存取旗標。當檔案已經存在時，若
   *exist_ok* 為 true 則函式不會失敗（其變更時間會被更新為當下時間），
   否則會引發 "FileExistsError"。

   也參考:

     The "open()", "write_text()" and "write_bytes()" methods are
     often used to create files.

Path.mkdir(mode=0o777, parents=False, exist_ok=False)

   在給定路徑下建立一個新的目錄。如果有給 *mode* 則會結合行程
   (process) 的 "umask" 值來決定檔案模式與存取旗標 (access flag)。如果
   路徑已經存在，會引發 "FileExistsError"。

   如果 *parents* 是 true，則任何缺少的父路徑都會依需要被建立；它們不
   考慮 *mode* 而會以預設的權限來建立（模仿 POSIX 的 "mkdir -p" 指令）
   。

   如果 *parents* 是 false（預設值），缺少的父路徑會引發
   "FileNotFoundError"。

   如果 *exist_ok* 是 false（預設值），則當目標目錄已經存在的話會引發
   "FileExistsError"。

   如果 *exist_ok* 是 true，只有當最後的路徑組成不是一個已存在的非目錄
   檔案，"FileExistsError" 例外會被忽略（與 POSIX 的 "mkdir -p" 指令行
   為相同）。

   在 3.5 版的變更: 新增 *exist_ok* 參數。

Path.symlink_to(target, target_is_directory=False)

   使這個路徑成為一個指向 *target* 的符號連結。

   在 Windows 上，符號連結代表一個檔案或目錄，且不會隨著目標 (target)
   動態改變。如果目標存在，則符號連結的類型會被建立來符合其目標。否則
   如果 *target_is_directory* 是 true，該符號連結會被建立成目錄，如果
   不是則建立成檔案（預設值）。在非 Windows 平台上，
   *target_is_directory* 會被忽略。

      >>> p = Path('mylink')
      >>> p.symlink_to('setup.py')
      >>> p.resolve()
      PosixPath('/home/antoine/pathlib/setup.py')
      >>> p.stat().st_size
      956
      >>> p.lstat().st_size
      8

   備註:

     引數的順序 (link, target) 和 "os.symlink()" 相反。

Path.hardlink_to(target)

   使這個路徑成為與 *target* 相同檔案的一個硬連結 (hard link)。

   備註:

     引數的順序 (link, target) 和 "os.link()" 相反。

   在 3.10 版被加入.


Renaming and deleting
---------------------

Path.rename(target)

   將此檔案或目錄重新命名為給定的 *target* ，並回傳一個新的 "Path" 實
   例指向該 *target*。在 Unix 系統上，若 *target* 存在且為一個檔案，若
   使用者有權限，則會在不顯示訊息的情況下進行取代。在 Windows 系統上，
   若 *target* 存在，則會引發 "FileExistsError" 錯誤。*target* 可以是
   字串或另一個路徑物件：

      >>> p = Path('foo')
      >>> p.open('w').write('some text')
      9
      >>> target = Path('bar')
      >>> p.rename(target)
      PosixPath('bar')
      >>> target.open().read()
      'some text'

   目標路徑可以是絕對路徑或相對路徑。相對路徑會相對於當前的工作目錄進
   行解釋，*而不是*相對於 "Path" 物件所在的目錄。

   此功能是使用 "os.rename()" 實現的，並提供相同的保證。

   在 3.8 版的變更: 新增了回傳值，回傳新的 "Path" 實例。

Path.replace(target)

   將此檔案或目錄重新命名為給定的 *target*，並回傳一個指向 *target* 的
   新 "Path" 實例。如果 *target* 指向一個現有的檔案或空目錄，它將被無
   條件地取代。

   目標路徑可以是絕對路徑或相對路徑。相對路徑會相對於當前的工作目錄進
   行解釋，*而不是*相對於 "Path" 物件所在的目錄。

   在 3.8 版的變更: 新增了回傳值，回傳新的 "Path" 實例。

Path.unlink(missing_ok=False)

   移除這個檔案或符號連結。如果路徑指向目錄，請改用 "Path.rmdir()"。

   如果 *missing_ok* 是 false（預設值），"FileNotFoundError" 會在路徑
   不存在時被引發。

   如果 *missing_ok* 是 true，"FileNotFoundError" 例外會被忽略（行為與
   POSIX "rm -f" 指令相同）。

   在 3.8 版的變更: 新增 *missing_ok* 參數。

Path.rmdir()

   移除此目錄。該目錄必須為空。


Permissions and ownership
-------------------------

Path.owner()

   回傳擁有該檔案的用戶名稱。如果在系統資料庫中找不到該檔案的使用者識
   別字 (UID)，則會引發 "KeyError"。

Path.group()

   回傳擁有該檔案的群組名稱。如果在系統資料庫裡找不到檔案的群組識別字
   (GID) 會引發 "KeyError"。

Path.chmod(mode, *, follow_symlinks=True)

   修改檔案模式 (file mode) 與權限，像 "os.chmod()" 一樣。

   此方法通常會跟隨符號連結。一些 Unix 類型支援修改符號連結本身的權限
   ；在這些平台上你可以加上引數 "follow_symlinks=False" 或使用
   "lchmod()"。

      >>> p = Path('setup.py')
      >>> p.stat().st_mode
      33277
      >>> p.chmod(0o444)
      >>> p.stat().st_mode
      33060

   在 3.10 版的變更: 新增 *follow_symlinks* 參數。

Path.lchmod(mode)

   類似 "Path.chmod()"，但如果該路徑指向一個符號連結，則符號連結的模式
   (mode) 會被改變而不是其指向的目標。


與 "os" 模組裡的工具的對應關係
==============================

以下是一張表格，對應許多 "os" 函式及其相符於 "PurePath"/"Path" 的項目
。

+---------------------------------------+------------------------------------------------+
| "os" 和 "os.path"                     | "pathlib"                                      |
|=======================================|================================================|
| "os.path.dirname()"                   | "PurePath.parent"                              |
+---------------------------------------+------------------------------------------------+
| "os.path.basename()"                  | "PurePath.name"                                |
+---------------------------------------+------------------------------------------------+
| "os.path.splitext()"                  | "PurePath.stem", "PurePath.suffix"             |
+---------------------------------------+------------------------------------------------+
| "os.path.join()"                      | "PurePath.joinpath()"                          |
+---------------------------------------+------------------------------------------------+
| "os.path.isabs()"                     | "PurePath.is_absolute()"                       |
+---------------------------------------+------------------------------------------------+
| "os.path.relpath()"                   | "PurePath.relative_to()" [1]                   |
+---------------------------------------+------------------------------------------------+
| "os.path.expanduser()"                | "Path.expanduser()" [2]                        |
+---------------------------------------+------------------------------------------------+
| "os.path.realpath()"                  | "Path.resolve()"                               |
+---------------------------------------+------------------------------------------------+
| "os.path.abspath()"                   | "Path.absolute()" [3]                          |
+---------------------------------------+------------------------------------------------+
| "os.path.exists()"                    | "Path.exists()"                                |
+---------------------------------------+------------------------------------------------+
| "os.path.isfile()"                    | "Path.is_file()"                               |
+---------------------------------------+------------------------------------------------+
| "os.path.isdir()"                     | "Path.is_dir()"                                |
+---------------------------------------+------------------------------------------------+
| "os.path.islink()"                    | "Path.is_symlink()"                            |
+---------------------------------------+------------------------------------------------+
| "os.path.isjunction()"                | "Path.is_junction()"                           |
+---------------------------------------+------------------------------------------------+
| "os.path.ismount()"                   | "Path.is_mount()"                              |
+---------------------------------------+------------------------------------------------+
| "os.path.samefile()"                  | "Path.samefile()"                              |
+---------------------------------------+------------------------------------------------+
| "os.getcwd()"                         | "Path.cwd()"                                   |
+---------------------------------------+------------------------------------------------+
| "os.stat()"                           | "Path.stat()"                                  |
+---------------------------------------+------------------------------------------------+
| "os.lstat()"                          | "Path.lstat()"                                 |
+---------------------------------------+------------------------------------------------+
| "os.listdir()"                        | "Path.iterdir()"                               |
+---------------------------------------+------------------------------------------------+
| "os.walk()"                           | "Path.walk()" [4]                              |
+---------------------------------------+------------------------------------------------+
| "os.mkdir()", "os.makedirs()"         | "Path.mkdir()"                                 |
+---------------------------------------+------------------------------------------------+
| "os.link()"                           | "Path.hardlink_to()"                           |
+---------------------------------------+------------------------------------------------+
| "os.symlink()"                        | "Path.symlink_to()"                            |
+---------------------------------------+------------------------------------------------+
| "os.readlink()"                       | "Path.readlink()"                              |
+---------------------------------------+------------------------------------------------+
| "os.rename()"                         | "Path.rename()"                                |
+---------------------------------------+------------------------------------------------+
| "os.replace()"                        | "Path.replace()"                               |
+---------------------------------------+------------------------------------------------+
| "os.remove()"、"os.unlink()"          | "Path.unlink()"                                |
+---------------------------------------+------------------------------------------------+
| "os.rmdir()"                          | "Path.rmdir()"                                 |
+---------------------------------------+------------------------------------------------+
| "os.chmod()"                          | "Path.chmod()"                                 |
+---------------------------------------+------------------------------------------------+
| "os.lchmod()"                         | "Path.lchmod()"                                |
+---------------------------------------+------------------------------------------------+

-[ 註解 ]-

[1] "os.path.relpath()" calls "abspath()" to make paths absolute and
    remove "".."" parts, whereas "PurePath.relative_to()" is a lexical
    operation that raises "ValueError" when its inputs' anchors differ
    (e.g. if one path is absolute and the other relative.)

[2] "os.path.expanduser()" returns the path unchanged if the home
    directory can't be resolved, whereas "Path.expanduser()" raises
    "RuntimeError".

[3] "os.path.abspath()" removes "".."" components without resolving
    symlinks, which may change the meaning of the path, whereas
    "Path.absolute()" leaves any "".."" components in the path.

[4] "os.walk()" always follows symlinks when categorizing paths into
    *dirnames* and *filenames*, whereas "Path.walk()" categorizes all
    symlinks into *filenames* when *follow_symlinks* is false (the
    default.)
