โฟลเดอร์ต้นทางและปลายทางบนโต๊ะมิ้นต์ มีลูกศรคัดลอกและย้ายไฟล์

Python 3.14: Path.copy / Path.move — คัดลอกและย้ายไฟล์โดยไม่ต้องเรียก shutil แยก

น้องกายEngineering

เวลาสคริปต์สำรองไฟล์ผมเคยสลับไปมาระหว่าง Path กับ shutil จนโค้ดดูขาด ๆ ครับ

ตั้งแต่ Python 3.14 คลาส pathlib.Path มีเมธอด copy / copy_into / move / move_into ในตัว (docs) — คัดลอกหรือย้ายไฟล์/ต้นไม้โฟลเดอร์แล้วได้ Path ใหม่ชี้ปลายทาง

จุดที่ควรรู้ก่อนใช้จริง:

  • copy(..., follow_symlinks=True) เป็นค่าเริ่มต้น — ตาม symlink ไปคัดลอกเป้า
  • preserve_metadata=True พยายามเก็บสิทธิ์/เวลา/xattr (บน Windows เมตาถูกเก็บอยู่แล้วตาม docs)
  • move ใช้ os.replace ถ้อยระบบเดียวกัน ไม่เช่นนั้นคัดลอกแล้วลบต้นทาง
  • copy_into / move_into ต้องการโฟลเดอร์ปลายทางที่มีอยู่แล้ว
import tempfile
import unittest
from pathlib import Path


class PathCopyMoveTests(unittest.TestCase):
    def test_copy_keeps_source(self):
        with tempfile.TemporaryDirectory() as tmp:
            root = Path(tmp)
            src = root / "note.txt"
            src.write_text("สวัสดี", encoding="utf-8")
            copied = src.copy(root / "note-copy.txt")
            self.assertEqual(copied.read_text(encoding="utf-8"), "สวัสดี")
            self.assertTrue(src.exists())

    def test_copy_into_directory(self):
        with tempfile.TemporaryDirectory() as tmp:
            root = Path(tmp)
            src = root / "a.bin"
            src.write_bytes(b"abc")
            folder = root / "box"
            folder.mkdir()
            out = src.copy_into(folder)
            self.assertEqual(out, folder / "a.bin")
            self.assertEqual(out.read_bytes(), b"abc")

    def test_move_renames_across_names(self):
        with tempfile.TemporaryDirectory() as tmp:
            root = Path(tmp)
            src = root / "old.txt"
            src.write_text("x", encoding="utf-8")
            dest = src.move(root / "new.txt")
            self.assertEqual(dest.name, "new.txt")
            self.assertFalse(src.exists())
            self.assertEqual(dest.read_text(encoding="utf-8"), "x")


if __name__ == "__main__":
    unittest.main()

Recap

  • อ่าน pathlib copy/move บน 3.14+
  • แทนคู่ shutil.copy2 + Path ด้วย Path.copy เมื่อทีมใช้ 3.14
  • ระวัง follow_symlinks ก่อนคัดลอกโฟลเดอร์ที่มีลิงก์
  • สร้างโฟลเดอร์ปลายทางก่อน copy_into / move_into