"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

   用於底層路徑剖析和結合的 "os.path" 模組的實作：可能是 "posixpath"
   或 "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
      ''

   這通常被稱為檔案副檔名。

   在 3.14 版的變更: A single dot (""."") is considered a valid
   suffix.

PurePath.suffixes

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

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

   在 3.14 版的變更: A single dot (""."") is considered a valid
   suffix.

PurePath.stem

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

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

   在 3.14 版的變更: A single dot (""."") is considered a valid
   suffix.

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

   自從版本 3.12 後不推薦使用，已從版本 3.14 中移除。: 額外引數的傳入
   已棄用；如果有的話，它們會與 *other* 連接在一起。

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"
   相同）。

   自從版本 3.12 後不推薦使用，已從版本 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')

   在 3.14 版的變更: A single dot (""."") is considered a valid
   suffix. In previous versions, "ValueError" is raised if a single
   dot is supplied.

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

   在 3.14 版的變更: The URL authority is discarded if it matches the
   local hostname. Otherwise, if the authority isn't empty or
   "localhost", then on Windows a UNC path is returned (as before),
   and on other platforms a "ValueError" is raised.

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'

   自從版本 3.14 後不推薦使用，將會自版本 3.19 中移除。: Calling this
   method from "PurePath" rather than "Path" is possible but
   deprecated. The method's use of "os.fsencode()" makes it strictly
   impure.


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

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" 而
不是引發例外。

在 3.14 版的變更: The methods given above now return "False" instead
of raising any "OSError" exception from the operating system. In
previous versions, some kinds of "OSError" exception are raised, and
others suppressed. The new behaviour is consistent with
"os.path.exists()", "os.path.isdir()", etc. Use "stat()" to retrieve
the file status without suppressing exceptions.

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)

   Return "True" if the path points to an existing file or directory.
   "False" will be returned if the path is invalid, inaccessible or
   missing. Use "Path.stat()" to distinguish between these cases.

   此方法通常會跟隨符號連結；如果想檢查符號連結是否存在，可以加上引數
   "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)

   Return "True" if the path points to a regular file. "False" will be
   returned if the path is invalid, inaccessible or missing, or if it
   points to something other than a regular file. Use "Path.stat()" to
   distinguish between these cases.

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

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

Path.is_dir(*, follow_symlinks=True)

   Return "True" if the path points to a directory. "False" will be
   returned if the path is invalid, inaccessible or missing, or if it
   points to something other than a directory. Use "Path.stat()" to
   distinguish between these cases.

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

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

Path.is_symlink()

   Return "True" if the path points to a symbolic link, even if that
   symlink is broken. "False" will be returned if the path is invalid,
   inaccessible or missing, or if it points to something other than a
   symbolic link. Use "Path.stat()" to distinguish between these
   cases.

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

   Return "True" if the path points to a Unix socket. "False" will be
   returned if the path is invalid, inaccessible or missing, or if it
   points to something other than a Unix socket. Use "Path.stat()" to
   distinguish between these cases.

Path.is_fifo()

   Return "True" if the path points to a FIFO. "False" will be
   returned if the path is invalid, inaccessible or missing, or if it
   points to something other than a FIFO. Use "Path.stat()" to
   distinguish between these cases.

Path.is_block_device()

   Return "True" if the path points to a block device. "False" will be
   returned if the path is invalid, inaccessible or missing, or if it
   points to something other than a block device. Use "Path.stat()" to
   distinguish between these cases.

Path.is_char_device()

   Return "True" if the path points to a character device. "False"
   will be returned if the path is invalid, inaccessible or missing,
   or if it points to something other than a character device. Use
   "Path.stat()" to distinguish between these cases.

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

   A "PathInfo" object that supports querying file type information.
   The object exposes methods that cache their results, which can help
   reduce the number of system calls needed when switching on file
   type. For example:

      >>> p = Path('src')
      >>> if p.info.is_symlink():
      ...     print('symlink')
      ... elif p.info.is_dir():
      ...     print('directory')
      ... elif p.info.exists():
      ...     print('something else')
      ... else:
      ...     print('not found')
      ...
      directory

   If the path was generated from "Path.iterdir()" then this attribute
   is initialized with some information about the file type gleaned
   from scanning the parent directory. Merely accessing "Path.info"
   does not perform any filesystem queries.

   To fetch up-to-date information, it's best to call "Path.is_dir()",
   "is_file()" and "is_symlink()" rather than methods of this
   attribute. There is no way to reset the cache; instead you can
   create a new path object with an empty info cache via "p =
   Path(p)".

   在 3.14 版被加入.


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

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'

   Return the number of characters written.

   一個名稱相同的已存在檔案會被覆寫。可選參數和 "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'

   Return the number of bytes written.

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

   在 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" 以總是跟隨符號連結。

   備註:

     從掃描檔案系統引發的任何 "OSError" 例外都會被抑制。這包括在存取沒
     有讀取權限的目錄時引發的 "PermissionError"。

   引發一個附帶引數 "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.

   備註:

     從掃描檔案系統引發的任何 "OSError" 例外都會被抑制。這包括在存取沒
     有讀取權限的目錄時引發的 "PermissionError"。

   也參考: 模式語言 (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, *, parent_mode=None)

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

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

   If *parent_mode* is not "None", it is used as the mode for any
   newly-created, intermediate-level directories when *parents* is
   true. Like *mode*, it is combined with the process's "umask" value.
   Otherwise, intermediate directories are created with the default
   permissions (also subject to the umask).

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

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

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

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

   在 3.15 版被加入: The *parent_mode* parameter.

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.copy(target, *, follow_symlinks=True, preserve_metadata=False)

   將此檔案或目錄樹複製到給定的 *target*，並回傳一個指向 *target* 的新
   "Path" 實例。

   If the source is a file, the target will be replaced if it is an
   existing file. If the source is a symlink and *follow_symlinks* is
   true (the default), the symlink's target is copied. Otherwise, the
   symlink is recreated at the destination.

   If *preserve_metadata* is false (the default), only directory
   structures and file data are guaranteed to be copied. Set
   *preserve_metadata* to true to ensure that file and directory
   permissions, flags, last access and modification times, and
   extended attributes are copied where supported. This argument has
   no effect when copying files on Windows (where metadata is always
   preserved).

   備註:

     Where supported by the operating system and file system, this
     method performs a lightweight copy, where data blocks are only
     copied when modified. This is known as copy-on-write.

   在 3.14 版被加入.

Path.copy_into(target_dir, *, follow_symlinks=True, preserve_metadata=False)

   Copy this file or directory tree into the given *target_dir*, which
   should be an existing directory. Other arguments are handled
   identically to "Path.copy()". Returns a new "Path" instance
   pointing to the copy.

   在 3.14 版被加入.

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.move(target)

   將此檔案或目錄樹移動到給定的 *target*，並回傳一個指向 *target* 的新
   "Path" 實例。

   If the *target* doesn't exist it will be created. If both this path
   and the *target* are existing files, then the target is
   overwritten. If both paths point to the same file or directory, or
   the *target* is a non-empty directory, then "OSError" is raised.

   If both paths are on the same filesystem, the move is performed
   with "os.replace()". Otherwise, this path is copied (preserving
   metadata and symlinks) and then deleted.

   在 3.14 版被加入.

Path.move_into(target_dir)

   Move this file or directory tree into the given *target_dir*, which
   should be an existing directory. Returns a new "Path" instance
   pointing to the moved path.

   在 3.14 版被加入.

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


Protocols
=========

The "pathlib.types" module provides types for static type checking.

在 3.14 版被加入.

class pathlib.types.PathInfo

   A "typing.Protocol" describing the "Path.info" attribute.
   Implementations may return cached results from their methods.

   exists(*, follow_symlinks=True)

      如果路徑是個存在的檔案、目錄或任何其他類型的檔案則回傳 "True"，
      如果路徑不存在則回傳 "False"。

      If *follow_symlinks* is "False", return "True" for symlinks
      without checking if their targets exist.

   is_dir(*, follow_symlinks=True)

      Return "True" if the path is a directory, or a symbolic link
      pointing to a directory; return "False" if the path is (or
      points to) any other kind of file, or if it doesn't exist.

      If *follow_symlinks* is "False", return "True" only if the path
      is a directory (without following symlinks); return "False" if
      the path is any other kind of file, or if it doesn't exist.

   is_file(*, follow_symlinks=True)

      Return "True" if the path is a file, or a symbolic link pointing
      to a file; return "False" if the path is (or points to) a
      directory or other non-file, or if it doesn't exist.

      If *follow_symlinks* is "False", return "True" only if the path
      is a file (without following symlinks); return "False" if the
      path is a directory or other non-file, or if it doesn't exist.

   is_symlink()

      Return "True" if the path is a symbolic link (even if broken);
      return "False" if the path is a directory or any kind of file,
      or if it doesn't exist.
