🐍 Ngày 36 - Python hằng ngày 365 ngày - Làm việc với pathlib trong Python
🎯 Mục tiêu:
- Làm quen với thư viện
pathlibđể thao tác với file và thư mục một cách hiện đại và tiện lợi hơnos.
🔧 Nội dung:
✅ Import thư viện
from pathlib import Path
✅ Tạo một thư mục mới
folder = Path("demo_folder")
folder.mkdir(exist_ok=True)
print(f"Đã tạo hoặc kiểm tra tồn tại: {folder}")
✅ Tạo một file trong thư mục đó
file = folder / "hello.txt"
file.write_text("Chào bạn từ pathlib!")
print(f"Đã ghi file: {file}")
✅ Đọc lại nội dung file
print("Nội dung file:", file.read_text())
📌 Ghi chú:
Path()là cách khởi tạo đường dẫn./dùng để nối các thành phần đường dẫn (giốngos.path.join()).write_text()vàread_text()giúp thao tác văn bản đơn giản hơn.
⏭ Tiếp tục với Ngày 37: Đọc ghi file JSON bằng pathlib + json
🔍 Vì sao pathlib tốt hơn os.path
So sánh cùng một công việc:
| Công việc | os.path (cũ) | pathlib (mới) |
|---|---|---|
| Nối đường dẫn | os.path.join("a", "b", "c.txt") | Path("a") / "b" / "c.txt" |
| Lấy tên file | os.path.basename(p) | Path(p).name |
| Lấy phần mở rộng | os.path.splitext(p)[1] | Path(p).suffix |
| Lấy thư mục cha | os.path.dirname(p) | Path(p).parent |
| Kiểm tra tồn tại | os.path.exists(p) | Path(p).exists() |
| Đường dẫn tuyệt đối | os.path.abspath(p) | Path(p).resolve() |
| Đọc file | open(p).read() | Path(p).read_text() |
Lợi ích lớn nhất: Path là đối tượng, không phải chuỗi. Bạn có thể gọi method trên nó, nối bằng /, và code chạy đúng trên cả Windows và Linux.
from pathlib import Path
# Trên Windows: Path("data") / "nam-2026" / "bao-cao.csv"
# → data\nam-2026\bao-cao.csv
# Trên Linux: → data/nam-2026/bao-cao.csv
# CÙNG MỘT DÒNG CODE, đúng cả hai nơi
file = Path("data") / "nam-2026" / "bao-cao.csv"
🛠️ Các thuộc tính và method quan trọng
from pathlib import Path
p = Path("data/bao-cao-2026.csv")
# --- Thuộc tính ---
print(p.name) # bao-cao-2026.csv
print(p.stem) # bao-cao-2026 (không có phần mở rộng)
print(p.suffix) # .csv
print(p.parent) # data
print(p.parts) # ('data', 'bao-cao-2026.csv')
print(p.is_absolute()) # False
print(p.anchor) # '' trên Linux, 'C:\\' trên Windows
# --- Kiểm tra ---
print(p.exists()) # File có tồn tại?
print(p.is_file()) # Là file?
print(p.is_dir()) # Là thư mục?
# --- Chuyển đổi ---
print(p.resolve()) # Đường dẫn tuyệt đối, đã chuẩn hoá
print(p.with_suffix(".json")) # data/bao-cao-2026.json
print(p.with_name("khac.csv")) # data/khac.csv
📂 Tạo, di chuyển, xoá
from pathlib import Path
import shutil
thu_muc = Path("du-an")
# Tạo thư mục (exist_ok=True để không lỗi nếu đã có)
thu_muc.mkdir(parents=True, exist_ok=True)
# Tạo nhiều thư mục con cùng lúc
for ten in ("du-lieu", "bao-cao", "log"):
(thu_muc / ten).mkdir(exist_ok=True)
# Ghi và đọc text
file = thu_muc / "ghi-chu.txt"
file.write_text("Nội dung ghi chú", encoding="utf-8")
print(file.read_text(encoding="utf-8"))
# Ghi và đọc nhị phân (ảnh, file nén...)
anh = thu_muc / "logo.png"
# anh.write_bytes(du_lieu_nhi_phan)
# du_lieu = anh.read_bytes()
# Di chuyển / đổi tên
dich = thu_muc / "ghi-chu-moi.txt"
file.rename(dich)
# Sao chép (dùng shutil)
shutil.copy2(dich, thu_muc / "sao-chep.txt")
# Xoá file
if dich.exists():
dich.unlink()
# Xoá thư mục rỗng
# (thu_muc / "rong").rmdir()
⚠️
unlink()vàrmdir()không hỏi lại. Nếu bạn chạyPath("du-lieu").unlink()mà trỏ nhầm vào file quan trọng, nó mất ngay. Không có thùng rác. Hãy kiểm tra kỹ đường dẫn trước khi xoá — và không bao giờ dùng vòng lặpunlink()mà không xem danh sách trước.
🔎 Tìm file với glob
from pathlib import Path
thu_muc = Path("du-an")
# Tất cả file .csv trong thư mục này
for f in thu_muc.glob("*.csv"):
print(f.name)
# Tất cả file .csv trong MỌI thư mục con
for f in thu_muc.rglob("*.csv"):
print(f.relative_to(thu_muc))
# Nhiều mẫu cùng lúc
for mau in ("*.csv", "*.xlsx", "*.json"):
for f in thu_muc.rglob(mau):
print(f"{f.stat().st_size:>10,} bytes {f.name}")
# Chỉ lấy file (bỏ thư mục)
file_csv = [f for f in thu_muc.rglob("*.csv") if f.is_file()]
print(f"Tìm thấy {len(file_csv)} file CSV")
Bảng mẫu glob hay dùng:
| Mẫu | Khớp với |
|---|---|
*.txt | Mọi file .txt |
bao-cao-*.csv | Bắt đầu bằng bao-cao- |
2026-??.xlsx | ? = đúng một ký tự bất kỳ |
**/*.py | Mọi file .py trong mọi thư mục con |
Thông tin file
from pathlib import Path
from datetime import datetime
f = Path("du-an/bao-cao.csv")
if f.exists():
st = f.stat()
print(f"Kích thước: {st.st_size / 1024:.1f} KB")
print(f"Sửa lần cuối: {datetime.fromtimestamp(st.st_mtime):%d/%m/%Y %H:%M}")
🧹 Ứng dụng thực tế: dọn file cũ hơn 30 ngày
from pathlib import Path
from datetime import datetime, timedelta
def don_file_cu(thu_muc: Path, so_ngay: int = 30, mo_phong: bool = True) -> int:
"""Xoá file cũ hơn `so_ngay` ngày. Mặc định chỉ MÔ PHỎNG."""
han = datetime.now() - timedelta(days=so_ngay)
so_luong = 0
for f in thu_muc.rglob("*.log"):
if not f.is_file():
continue
ngay_sua = datetime.fromtimestamp(f.stat().st_mtime)
if ngay_sua < han:
if mo_phong:
print(f"[MÔ PHỎNG] sẽ xoá: {f} (sửa {ngay_sua:%d/%m/%Y})")
else:
f.unlink()
print(f"Đã xoá: {f}")
so_luong += 1
return so_luong
# Luôn chạy mô phỏng trước!
print(don_file_cu(Path("logs"), so_ngay=30, mo_phong=True))
📝 Bài tập mở rộng
Bài 1: Đếm file theo loại
Tạo cấu trúc thư mục với nhiều loại file khác nhau, rồi viết script đếm số file mỗi loại (.py, .csv, .txt, .json) và tổng dung lượng.
Bài 2: Đổi tên hàng loạt
Đổi tên mọi file .jpeg thành .jpg trong một thư mục (dùng with_suffix()).
Bài 3: Tìm file trùng tên trong nhiều thư mục
Dùng rglob() và collections.Counter để tìm file có cùng tên ở nhiều nơi.
Bài 4: Cây thư mục
In ra cây thư mục (giống lệnh tree) từ một thư mục, dùng đệ quy để đi vào thư mục con.
🎯 Tóm tắt ngày 36
✅ Dùng Path thay os.path — code sạch hơn, chạy đa nền tảng
✅ Nối đường dẫn bằng dấu /
✅ mkdir(parents=True, exist_ok=True) tạo thư mục an toàn
✅ read_text/write_text gọn hơn open()
✅ glob/rglob tìm file theo mẫu
✅ Luôn chạy mô phỏng trước khi xoá file
🚀 Bắt đầu với Python
Bạn có thể mở bài học này trên Google Colab để chạy trực tiếp: