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

在 3.4 版被加入.

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

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

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

[圖片：顯示 pathlib 中可用類別的繼承圖。 最基礎的類別是 PurePath，它有
三個直接子類別： PurePosixPath、PureWindowsPath 和 Path。除了這四個類
別之外， 還有兩個類別使用多重繼承： PosixPath 繼承自 PurePosixPath 和
Path，而 WindowsPath 繼承自 PureWindowsPath 和 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'


例外
====

exception pathlib.UnsupportedOperation

   繼承自 "NotImplementedError" 的例外，當在路徑物件上呼叫不支援的操作
   時會被引發。

   在 3.13 版被加入.


純路徑
======

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

class pathlib.PurePath(*pathsegments)

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

      >>> PurePath('setup.py')      # 執行在 Unix 機器上
      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/hosts')
      PurePosixPath('/etc/hosts')

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

class pathlib.PureWindowsPath(*pathsegments)

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

      >>> PureWindowsPath('c:/', 'Users', 'Ximénez')
      PureWindowsPath('c:/Users/Ximénez')
      >>> 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.parser

   The implementation of the "os.path" module used for low-level path
   parsing and joining: either "posixpath" or "ntpath".

   在 3.13 版被加入.

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

   一個路徑後綴 (suffix) 的串列，通常被稱為檔案副檔名：

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

PurePath.stem

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

      >>> 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.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"
   。

   在 3.13 版的變更: Windows 路徑名稱中包含冒號或結尾為點或空格會被視
   為保留。UNC 路徑可能被視為保留。

   Deprecated since version 3.13, will be removed in version 3.15: 此
   方法已被棄用；請使用 "os.path.isreserved()" 來檢測 Windows 上的保留
   路徑。

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.full_match(pattern, *, case_sensitive=None)

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

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

   也參考: 模式語言 (pattern language) 文件。

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

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

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

   在 3.13 版被加入.

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

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

   此方法類似於 "full_match()"，但不允許空白模式（會引發 "ValueError"
   ）、不支援遞迴萬用字元 ""**""（它會像非遞迴的 ""*"" 一樣），且如果
   提供相對模式，則會從右邊進行比對：

      >>> 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

   在 3.12 版的變更: *pattern* 參數接受*類路徑物件*。

   在 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/hosts')
      PosixPath('/etc/hosts')

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

   在 3.13 版的變更: 在 Windows 上會引發 "UnsupportedOperation"。在先
   前版本中，則是引發 "NotImplementedError"。

class pathlib.WindowsPath(*pathsegments)

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

      >>> WindowsPath('c:/', 'Users', 'Ximénez')
      WindowsPath('c:/Users/Ximénez')

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

   在 3.13 版的變更: 在非 Windows 平台上會引發 "UnsupportedOperation"
   。在先前版本中，則是引發 "NotImplementedError"。

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

   >>> 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__,))
   UnsupportedOperation: cannot instantiate 'WindowsPath' on your system

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


剖析和產生 URI
--------------

實體路徑物件可以從符合 **RFC 8089** 中的 'file' URI 建立，也可以以該形
式來表示。

備註:

  檔案 URI 在跨不同檔案系統編碼的機器上是無法移植的。

classmethod Path.from_uri(uri)

   從剖析 'file' URI 回傳新的路徑物件。例如：

      >>> p = Path.from_uri('file:///etc/hosts')
      PosixPath('/etc/hosts')

   在 Windows 上，從 URI 可以剖析 DOS 裝置和 UNC 路徑：

      >>> p = Path.from_uri('file:///c:/windows')
      WindowsPath('c:/windows')
      >>> p = Path.from_uri('file://server/share')
      WindowsPath('//server/share')

   支援多種變形：

      >>> p = Path.from_uri('file:////server/share')
      WindowsPath('//server/share')
      >>> p = Path.from_uri('file://///server/share')
      WindowsPath('//server/share')
      >>> p = Path.from_uri('file:c:/windows')
      WindowsPath('c:/windows')
      >>> p = Path.from_uri('file:/c|/windows')
      WindowsPath('c:/windows')

   如果 URI 不是 "file:" 開頭，或是剖析後的路徑不是絕對路徑，則會引發
   "ValueError"。

   在 3.13 版被加入.

Path.as_uri()

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

      >>> p = PosixPath('/etc/passwd')
      >>> p.as_uri()
      'file:///etc/passwd'
      >>> p = WindowsPath('c:/Windows')
      >>> p.as_uri()
      'file:///c:/Windows'

   因為歷史上的原因，此方法也可以從 "PurePath" 物件上使用。然而，它使
   用 "os.fsencode()" 而讓它完全不純粹。


擴展和解析路徑
--------------

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"，則引發
   "OSError"。如果 *strict* 為 "False"，則將盡可能解析該路徑，並將任何
   剩餘部分追加到路徑中，而不檢查其是否存在。

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

   在 3.13 版的變更: 在嚴格模式下，符號連結迴圈會像其他錯誤一樣來處理
   ："OSError" 會被引發，而在非嚴格模式下，不會引發任何例外。在先前版
   本中，不管 *strict* 的值是什麼，都會引發 "RuntimeError"。

Path.readlink()

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

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

   在 3.9 版被加入.

   在 3.13 版的變更: 如果 "os.readlink()" 不可用，會引發
   "UnsupportedOperation"。在先前版本中，則是引發
   "NotImplementedError"。


查詢檔案類型和狀態
------------------

在 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)

   回傳一個包含該路徑資訊的 "os.stat_result" 物件，像 "os.stat()" 一樣
   。每次呼叫此方法都會重新查詢結果。

   此方法通常會跟隨 (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(*, follow_symlinks=True)

   如果該路徑指向一個普通檔案則回傳 "True"，如果指向其他類型的檔案則回
   傳 "False"。

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

   此方法通常會跟隨符號連結；如果想將符號連結除外，可以加上引數
   "follow_symlinks=False"。

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

Path.is_dir(*, follow_symlinks=True)

   如果該路徑指向一個目錄則回傳 "True"，如果指向其他類型的檔案則回傳
   "False"。

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

   此方法通常會跟隨符號連結；如果想將對目錄的符號連結除外，可以加上引
   數 "follow_symlinks=False"。

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

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 版被加入.


讀取和寫入檔案
--------------

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, newline=None)

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

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

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

   在 3.5 版被加入.

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

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，且不會包含特殊項目 "'.'" 和 "'..'"。如
   果一個檔案在建立這個疊代器之後加到該目錄或從目錄刪除，這個檔案的路
   徑物件是否會被包含是沒有明定的。

   如果路徑不是目錄或無法存取，則會引發 "OSError"。

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

   在該路徑表示的目錄裡，以 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')]
      >>> sorted(Path('.').glob('**/*.py'))
      [PosixPath('build/lib/pathlib.py'),
       PosixPath('docs/conf.py'),
       PosixPath('pathlib.py'),
       PosixPath('setup.py'),
       PosixPath('test_pathlib.py')]

   備註:

     The paths are returned in no particular order. If you need a
     specific order, sort the results.

   也參考: 模式語言 (pattern language) 文件。

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

   預設情況下，或者當 *recurse_symlinks* 僅限關鍵字引數被設定為
   "False" 的時候，此方法會跟隨符號連結，除非在擴展 ""**"" 萬用字元時
   。將 *recurse_symlinks* 設成 "True" 以總是跟隨符號連結。

   引發一個附帶引數 "self"、"pattern" 的稽核事件 "pathlib.Path.glob"。

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

   在 3.13 版的變更: 新增 *recurse_symlinks* 參數。

   在 3.13 版的變更: *pattern* 參數接受*類路徑物件*。

   在 3.13 版的變更: 從掃描檔案系統引發的任何 "OSError" 例外都會被抑制
   。在先前版本中，在許多情況下這種例外都會被抑制，但不是所有情況。

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

   遞迴地 glob 給定的相對 *pattern*。這相當於在給定的相對 *pattern* 前
   面加上 ""**/"" 並呼叫 "Path.glob()"。

   備註:

     The paths are returned in no particular order. If you need a
     specific order, sort the results.

   也參考: 模式語言 (pattern language) 和 "Path.glob()" 文件。

   引發一個附帶引數 "self"、"pattern" 的稽核事件 "pathlib.Path.rglob"
   。

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

   在 3.13 版的變更: 新增 *recurse_symlinks* 參數。

   在 3.13 版的變更: *pattern* 參數接受*類路徑物件*。

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()" 不允許在目錄為空之前刪除它：

      # 刪除可從 "top" 目錄到達的所有東西。
      # 注意：這是危險的！例如，如果 top == Path('/')，
      # 它可能會刪除你所有的檔案。
      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"。

   也參考: "open()"、"write_text()" 和 "write_bytes()" 方法通常用於建立檔案
        。

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()" 相反。

   在 3.13 版的變更: 如果 "os.symlink()" 不可用，會引發
   "UnsupportedOperation"。在先前版本中，則是引發
   "NotImplementedError"。

Path.hardlink_to(target)

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

   備註:

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

   在 3.10 版被加入.

   在 3.13 版的變更: 如果 "os.link()" 不可用，會引發
   "UnsupportedOperation"。在先前版本中，則是引發
   "NotImplementedError"。


重新命名和刪除
--------------

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()

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


權限和所有權
------------

Path.owner(*, follow_symlinks=True)

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

   此方法通常會跟隨符號連結；如果想取得符號連結的擁有者，可以加上引數
   "follow_symlinks=False"。

   在 3.13 版的變更: 如果 "pwd" 模組不可用，會引發
   "UnsupportedOperation"。在先前版本中，則是引發
   "NotImplementedError"。

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

Path.group(*, follow_symlinks=True)

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

   此方法通常會跟隨符號連結；如果想取得符號連結的群組，可以加上引數
   "follow_symlinks=False"。

   在 3.13 版的變更: 如果 "grp" 模組不可用，會引發
   "UnsupportedOperation"。在先前版本中，則是引發
   "NotImplementedError"。

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

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) 會被改變而不是其指向的目標。


模式語言 (pattern language)
===========================

以下的萬用字元在 "full_match()"、"glob()" 和 "rglob()" 的模式中被支援
：

"**"（整個片段）
   匹配任何數量的檔案或目錄片段，包括零個。

"*"（整個片段）
   匹配一個檔案或目錄的片段。

"*"（片段的一部分）
   匹配任意數量的非分隔字元，包括零個。

"?"
   匹配一個非分隔字元。

"[seq]"
   Matches one character in *seq*, where *seq* is a sequence of
   characters. Range expressions are supported; for example, "[a-z]"
   matches any lowercase ASCII letter. Multiple ranges can be
   combined: "[a-zA-Z0-9_]" matches any ASCII letter, digit, or
   underscore.

"[!seq]"
   匹配一個不在 *seq* 中的字元，其中 *seq* 遵循上述相同的規則。

對於文本 (literal) 匹配，可以用方括號包裝元字元 (meta-characters)。例
如，""[?]"" 會匹配字元 ""?""。

""**"" 萬用字元讓它可以做遞迴 glob。例如：

+---------------------------+-----------------------------------------------------------------------+
| 模式                      | 意涵                                                                  |
|===========================|=======================================================================|
| ""**/*""                  | 至少有一個片段的路徑。                                                |
+---------------------------+-----------------------------------------------------------------------+
| ""**/*.py""               | 最後一個片段以 "".py"" 結尾的任何路徑。                               |
+---------------------------+-----------------------------------------------------------------------+
| ""assets/**""             | 任何以 ""assets/"" 開頭的路徑。                                       |
+---------------------------+-----------------------------------------------------------------------+
| ""assets/**/*""           | 任何以 ""assets/"" 開頭的路徑，不包括 ""assets/"" 本身。              |
+---------------------------+-----------------------------------------------------------------------+

備註:

  Glob 使用 "**" 萬用字元會訪問目錄樹中的每個目錄。對於大型的目錄樹，
  搜尋可能需要花費很長的時間。

在 3.13 版的變更: Glob 使用結尾為 "**" 的模式會同時回傳檔案和目錄。在
先前版本中，只會回傳目錄。

在 "Path.glob()" 和 "rglob()" 中，可以在模式後面加上斜線以只匹配目錄。

在 3.11 版的變更: Glob 使用以路徑名稱組成的分隔符號（"sep" 或 "altsep"
）作結尾的模式則只會回傳目錄。


與 "glob" 模組的比較
====================

"Path.glob()" 和 "Path.rglob()" 接受的模式和產生的結果與 "glob" 模組略
有不同：

1. pathlib 中以點開頭的檔案並不特別。這和將 "include_hidden=True" 傳遞
   給 "glob.glob()" 相同。

2. "**" 模式組成在 pathlib 中總是遞迴的。這與將 "recursive=True" 傳遞
   給 "glob.glob()" 相同。

3. 在 pathlib 中，"**" 模式組成預設不跟隨符號連結。這在 "glob.glob()"
   中沒有等效的行為，但你可以將 "recurse_symlinks=True" 傳遞給
   "Path.glob()" 以獲得相容的行為。

4. 與所有 "PurePath" 和 "Path" 物件一樣，從 "Path.glob()" 和
   "Path.rglob()" 回傳的值不包含結尾斜線。

5. pathlib 的 "path.glob()" 和 "path.rglob()" 回傳的值包含了 *path* 作
   為前綴，而 "glob.glob(root_dir=path)" 的結果則不會如此。

6. pathlib 的 "path.glob()" 和 "path.rglob()" 回傳的值可能包含 *path*
   本身，例如當使用 ""**"" 做 glob 的時候，然而
   "glob.glob(root_dir=path)" 的結果則永遠不會包含一個對應到 *path* 的
   空字串。


與 "os" 和 "os.path" 模組的比較
===============================

pathlib 使用 "PurePath" 和 "Path" 物件來實作路徑操作，因此它被稱為是*
物件導向*的。另一方面，"os" 和 "os.path" 模組提供能夠與底層 "str" 和
"bytes" 物件互動的函式，這是一種更*程序式*的方法。有些使用者認為物件導
向的風格更易讀。

"os" 和 "os.path" 中的許多函式支援 "bytes" 路徑和相對路徑的目錄描述器
(paths relative to directory descriptors)。這些功能在 pathlib 中不可用
。

Python 的 "str" 和 "bytes" 型別，以及 "os" 和 "os.path" 模組的一些部分
，是用 C 寫的且非常快速。pathlib 是用純 Python 寫的且通常比較慢，但很
少會慢到足以產生影響。

pathlib 的路徑正規化略比 "os.path" 更武斷和一致。例如，儘管
"os.path.abspath()" 會從路徑中移除 "".."" 片段，如果包含符號連結的話這
可能會改變其意義，而 "Path.absolute()" 則會保留這些片段以增加安全性。

pathlib 的路徑正規化可能會使它不適合某些應用程式：

1. pathlib 將 "Path("my_folder/")" 正規化為 "Path("my_folder")"，這會
   在提供給各種操作系統 API 和命令列工具時改變路徑的意義。具體來說，缺
   少結尾分隔符號可能會允許該路徑被解析為檔案或目錄，而不只是目錄。

2. pathlib 將 "Path("./my_program")" 正規化為 "Path("my_program")"，這
   會在作為執行檔搜尋路徑使用時改變路徑的意義，例如在 shell 或在衍生
   (spawn) 子行程時。具體來說，在路徑中缺少分隔符號可能會使其強制在
   "PATH" 中尋找，而不是目前目錄。

因為這些差異，pathlib 不是 "os.path" 的直接替代品。


對應工具
--------

以下是一張表格，對應許多 "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()" 會呼叫 "abspath()" 來將路徑變成絕對路徑並移除
    "".."" 部分，而 "PurePath.relative_to()" 是一個文本上的操作，當它
    輸入的錨點不同時（例如一個是絕對路徑，另一個則是相對路徑）會引發
    "ValueError"。

[2] "os.path.expanduser()" 會在無法解析家目錄時回傳原始路徑，而
    "Path.expanduser()" 則會引發 "RuntimeError"。

[3] "os.path.abspath()" 將 "".."" 組成移除而不解析符號連結，這可能會改
    變路徑的意義，而 "Path.absolute()" 則會保留路徑中任何 "".."" 組成
    。

[4] 當分類路徑成 *dirnames* 和 *filenames* 時 "os.walk()" 總是跟隨符號
    連結，而 "Path.walk()" 在 *follow_symlinks* 為 false（預設值）時，
    會將所有符號連結都分類為 *filenames*。
