---
# System prepended metadata

title: Pathlib
tags: [Python]

---

---
tags: Python
---
# Pathlib

Python 文件給 Pathlib 的定義是 Object-oriented filesystem paths **物件導向的檔案系統路徑**。
Python 3.4 以上加入 [pathlib](https://docs.python.org/3/library/pathlib.html) ，先前的版本也能夠透過 pip 安裝使用。
對文件路徑的操作更加優化。它不單純是為了簡化操作，還有更大的用途。pathlib 不單純是對 os 中一些模組或方法進行封裝，而是為了相容不同的作業系統，它為每類作業系統定義了介面。

![](https://i.imgur.com/1Gj7ZXg.png)

 * `PurePath` ：提供純計算操作，**無提供 I/O** 的純路徑。無論什麼系統都可以宣告其他系統的 PurePath ，因為它們不提供任何進行系統呼叫的操作。純路徑在某些特殊情況下很有用；例如：如果要在 Unix 上操作 Windows 路徑（反之亦然）。
 * `Path` ：繼承自 PurePath ，**有提供 I/O** 操作。
> Path classes are divided between pure paths, which provide purely computational operations without I/O, and concrete paths, which inherit from pure paths but also provide I/O operations.
> 
> Regardless of the system you’re running on, you can instantiate all of these classes, since they don’t provide any operation that does system calls.

 * `PosixPath` ：Unix-like 檔案系統。
 * `WindowsPath` ：Windows 檔案系統。

## 與 `os.path` 比較

很多操作也都變超簡單，~~`os.path` 真的很雞肋~~：

### 宣告

```python
import os.path
folder_os = os.path.join("source_data", "text_files")
file_os = os.path.join(folder_os, "raw_data.txt")
---
from pathlib import Path
folder = Path('source_data/text_files/')
file = folder / 'raw_data.txt'
```

### 判斷檔案路徑存在

```python
os.path.exists(file_os)
---
file.exists()
```

### 讀寫檔

```python
with open(file_os) as f:
    print(f.read())
    f.write('Write something...')
---
print(file.read_text())
file.write_text('Write something...')
```

### 讀取檔名

```python
# -> 'raw_data.txt'
print(os.path.basename(file_os))
---
print(file.name)
```

### 讀取檔名（不要副檔名）

```python
# -> "raw_data"
print(os.path.splitext(os.path.basename(file_os))[0])
---
print(file.stem)
```

### 讀取檔案類別

```python
# -> '.txt'
print(os.path.splitext(file_os)[-1])
---
print(file.suffix)

# -> ['.tar', '.gz']
targz = Path('source_data/text_files/raw_data.tar.gz')
print('os: give up!!')
---
print(file.suffixes)
```

### 資料夾

```python
# 目前資料夾
Path.cwd()  # -> PosixPath('.../folder')

cwd = Path()  # -> 相對位置 PosixPath('.')
cwd.resolve()  # -> 絕對位置 PosixPath('.../folder')

# 抓取祖宗十八代
Path.cwd().parent      # -> PosixPath('/Users/catmao')
Path.cwd().parents[0]  # -> PosixPath('/Users/catmao')
Path.cwd().parents[1]  # -> PosixPath('/Users')

# 創建 / 刪除資料夾
folder = Path('docs')
folder.mkdir()
folder.is_dir()  # -> True
folder.rmdir()

# 新增 / 刪除檔案
file_1 = Path('file_1.txt')
file_1.touch()  # 新增
file_1.unlink()  # 刪除
file_2 = folder / 'file_2.txt'
file_2.write_text('Write something...')  # 新增並寫檔

# 顯示資料夾下的檔案
[item for item in Path('docs').glob('*.txt')]
# -> [PosixPath('docs/file_1.txt'), PosixPath('docs/file_2.txt')]

for i in Path('docs').iterdir():
    print(i)
# -> docs/file_1.txt
# -> docs/file_2.txt

# 遍歷所有資料夾 子子孫孫
[item for item in Path('docs').glob('**/*.txt')]
[item for item in Path('docs').rglob('*.txt')]

# 改名改姓
file_1.with_name('new_file_1.txt')  # -> new_file_1.txt
file_2.with_suffix('.md')  # -> file_2.md
```

## 參考資料

1. [PEP 428 The pathlib module -- object-oriented filesystem paths](https://www.python.org/dev/peps/pep-0428/)
2. [Pathlib Is Wonderful!](https://jefftriplett.com/2017/pathlib-is-wonderful/)
