Thứ Hai, 14 tháng 9, 2026

Đổi tên file hàng loạt bằng Python (Đừng "bình tĩnh" ngồi bấm F2 từng file nếu Python có thể làm thay bạn.)

Cho dù bạn có phải là "dân lập trình" hay không, chỉ cần bạn đã từng "mó" tới máy tính thì trong suốt "cuộc đời mày mò máy tính" nhất định sẽ có một lần bạn phải làm công việc đổi tên từng file một vô cùng nhàm chán và mệt mỏi! Một công việc mà dù có dễ tính mấy cũng không ai "tự hào" khoe khoang với thiên hạ.

Có một công việc nhìn rất đơn giản:
Đổi tên file.

Một file:

anh1.jpg
Bạn bấm F2.

Đổi thành:

sanpham_01.jpg
Xong.

File thứ hai:

anh2.jpg
F2.

Đổi tên.

File thứ ba...

F2.

File thứ tư...

F2.

...

Đến file thứ 300:

"Ủa... mình đang hành hạ cuộc đời của chính mình hả trời?" 

Nếu chỉ có 3–5 file thì làm bằng tay chẳng sao.

Nhưng nếu có:

100 file
500 file
1.000 file

thì đây chính là lúc Python bắt đầu có đất dụng võ.

Hôm nay chúng ta sẽ thử:
Cho Python đổi tên hàng loạt file thay mình.

Và đây cũng là một bước rất đẹp để bắt đầu hiểu Automation.

Python có thể đổi tên file thật sao?
Dĩ nhiên rồi.

Python không chỉ:

  • Tính toán
  • In chữ
  • Đọc CSV
Nó còn có thể làm việc với file và thư mục trên máy tính.

Ví dụ:

old_name.txt
có thể đổi thành:

new_name.txt
Hoặc:

  • anh1.jpg
  • anh2.jpg
  • anh3.jpg
  • ...
  • anh100.jpg
thành:

  • sanpham_001.jpg
  • sanpham_002.jpg
  • sanpham_003.jpg
  • ...
  • sanpham_100.jpg

Một chương trình.
Một lần chạy.
Cả đống file được xử lý.

Đây mới bắt đầu có mùi:
Automation. 

Module os là gì?

Python có module:

os
os cung cấp nhiều công cụ để làm việc với hệ điều hành.

Ví dụ:

  • xem thư mục
  • tạo thư mục
  • kiểm tra file
  • đổi tên file
  • xóa file
  • làm việc với đường dẫn
Chúng ta có thể bắt đầu bằng:

import os
Sau đó dùng:

os.rename()
để đổi tên file.

Đổi tên một file đầu tiên
Giả sử thư mục có:

old.txt
Bạn muốn đổi thành:

new.txt

Code:

import os

os.rename("old.txt", "new.txt")


Chạy chương trình.

File:

old.txt
biến thành:

new.txt


Không cần:

click chuột
F2
gõ tên
Enter
Python làm.


os.rename() thực sự đang làm gì?
Câu lệnh:

os.rename("old.txt", "new.txt")
có thể hiểu đơn giản:

"Hệ điều hành ơi, đổi tên file old.txt thành new.txt giúp tôi."

Trong đó:

old.txt
là tên cũ.

new.txt
là tên mới.


Đổi tên file trong thư mục khác

Giả sử cấu trúc:

my_project/

-main.py
-files/
    --old.txt

Bạn có thể viết:

import os

os.rename("files/old.txt", "files/new.txt")



Python sẽ đổi:
files/old.txt

thành:
files/new.txt

Điểm quan trọng ở đây:
Đường dẫn file phải đúng.

Đây là chỗ người mới tìm hiểu rất dễ gặp lỗi.

Lỗi kinh điển: FileNotFoundError 

Bạn viết:
os.rename("old.txt", "new.txt")

Nhưng Python báo:
FileNotFoundError

Bạn:
"Tào lao, rõ ràng file có ở đó mà?"

Python:
"Tôi không thấy."

Bạn:
"Nó nằm ngay trước mặt tôi!"

Python:
"Nhưng không nằm ở chỗ tôi đang tìm."



Đây là điểm rất quan trọng:

File Explorer đang mở ở đâu không có nghĩa Python đang tìm file ở đó.

Python làm việc dựa trên đường dẫn và thư mục hiện tại của chương trình.


Kiểm tra Python đang đứng ở đâu

Bạn có thể dùng:

import os

print(os.getcwd())

getcwd() là:

Get Current Working Directory

Nói đơn giản:

"Python ơi, hiện tại bạn đang đứng ở thư mục nào?"

Ví dụ:

C:\Users\An\Projects\my_project
Nếu bạn có:

C:\Users\An\Projects\my_project\files\old.txt
thì:

os.rename("files/old.txt", "files/new.txt")
mới hợp lý.


Kiểm tra file có tồn tại không
Trước khi đổi tên, bạn có thể kiểm tra:

import os

if os.path.exists("old.txt"):
    os.rename("old.txt", "new.txt")
else:
    print("Không tìm thấy file!")


Cách này giúp chương trình không lao đầu vào tường ngay lập tức. 

Nếu file tồn tại:

old.txt
→ đổi tên.

Nếu không:

Không tìm thấy file!

Nhưng đổi một file thì chưa có gì ghê gớm
Đúng vậy.

Nếu bạn chỉ cần đổi:
old.txt

thành:
new.txt

thì bấm F2 còn nhanh hơn viết Python. 

Vậy sức mạnh nằm ở đâu?

Ở đây:
Đổi hàng loạt.

Đổi tên 10 file bằng Python
Giả sử thư mục:

photos/

-img1.jpg
-img2.jpg
-img3.jpg
-img4.jpg
-img5.jpg

Bạn muốn thành:

  • product_01.jpg
  • product_02.jpg
  • product_03.jpg
  • product_04.jpg
  • product_05.jpg
Python có thể dùng vòng lặp:

import os

for i in range(1, 6):
    old_name = f"img{i}.jpg"
    new_name = f"product_{i:02d}.jpg"

    os.rename(old_name, new_name)


Kết quả:

  • img1.jpg → product_01.jpg
  • img2.jpg → product_02.jpg
  • img3.jpg → product_03.jpg
  • img4.jpg → product_04.jpg
  • img5.jpg → product_05.jpg

Một vòng for.

Năm file.

Nếu có 500 file thì sao?

Thay đổi:

range(1, 6)
thành:

range(1, 501)


f"..." là gì?
Bạn thấy:

old_name = f"img{i}.jpg"
Đây là f-string.

Nó cho phép đưa biến vào trong chuỗi.

Nếu:

i = 3
thì:

f"img{i}.jpg"
trở thành:

img3.jpg
Tương tự:

f"product_{i}.jpg"
với:

i = 3
sẽ thành:

product_3.jpg

Còn {i:02d} là gì?
Đây là một chi tiết rất hữu ích khi đặt tên file.

f"product_{i:02d}.jpg"
02d có thể hiểu đơn giản:

"Số nguyên, tối thiểu 2 chữ số. Thiếu thì thêm số 0 phía trước."

Ví dụ:

1  → 01
2  → 02
9  → 09
10 → 10

Vì vậy:

  • product_01.jpg
  • product_02.jpg
  • ...
  • product_09.jpg
  • product_10.jpg
Nhìn gọn hơn rất nhiều.


Tại sao không đặt product_1.jpg, product_2.jpg?

Bạn hoàn toàn có thể đặt bất cứ "phong cách" nào.

Nhưng khi số lượng file lớn, cách đánh số cố định giúp việc sắp xếp dễ hơn.

Ví dụ:

  • product_1.jpg
  • product_2.jpg
  • product_10.jpg
Một số cách sắp xếp có thể khiến thứ tự nhìn không như bạn mong muốn.

Trong khi:

  • product_01.jpg
  • product_02.jpg
  • product_10.jpg
thì nhìn rất rõ.

Với 100 file, bạn có thể dùng:

f"product_{i:03d}.jpg"

để có kết quả:

  • 001
  • 002
  • 003
  • ...
  • 100

Nhưng thực tế file thường không đẹp như vậy 
Đây mới là "sự thật phũ phàng".

Bạn không có "dream team":

  • img1.jpg
  • img2.jpg
  • img3.jpg
mà khả năng cao sẽ có:

  • IMG_8237.jpg
  • DSC_00482.jpg
  • photo-final.jpg
  • new.jpg
  • new-final.jpg
  • new-final-2.jpg
  • abc123.jpg


Lúc này không thể chỉ dùng:

for i in range(...)
rồi đoán tên file.

Chúng ta cần:

Đọc danh sách file thực tế trong thư mục.

Lấy danh sách file bằng os.listdir()

Python có:
os.listdir()

Ví dụ:

import os

files = os.listdir("photos")

print(files)


Nếu thư mục có:

  • IMG_8237.jpg
  • DSC_00482.jpg
  • photo-final.jpg
có thể nhận được:

['IMG_8237.jpg', 'DSC_00482.jpg', 'photo-final.jpg']

Python vừa:
"Đi vào thư mục."

và:
"Xem bên trong có gì."

Đổi tên toàn bộ file trong thư mục
Ví dụ:

import os

folder = "photos"

files = os.listdir(folder)

for i, filename in enumerate(files, start=1):
    old_path = os.path.join(folder, filename)
    new_name = f"photo_{i:03d}.jpg"
    new_path = os.path.join(folder, new_name)

    os.rename(old_path, new_path)


Ý tưởng:

Lấy danh sách file
       ↓
Duyệt từng file
       ↓
Tạo tên mới
       ↓
Đổi tên

Ví dụ:

  • IMG_8237.jpg       → photo_001.jpg
  • DSC_00482.jpg      → photo_002.jpg
  • photo-final.jpg    → photo_003.jpg

Đây mới thực sự là:
Đổi tên hàng loạt.

enumerate() là gì?
Đoạn code:

for i, filename in enumerate(files, start=1):

có nghĩa đơn giản:

"Duyệt qua từng file và đồng thời đánh số cho nó."

Ví dụ:

  • file A → 1
  • file B → 2
  • file C → 3
Nếu:

start=1
thì bắt đầu từ 1.

Nếu không ghi, enumerate() mặc định bắt đầu từ 0.

os.path.join() rất đáng nhớ
Bạn có:

folder = "photos"
và:

filename = "IMG_8237.jpg"
Bạn có thể nối chúng bằng:

os.path.join(folder, filename)
Kết quả sẽ tạo đường dẫn phù hợp với hệ điều hành.

Ví dụ:

photos/IMG_8237.jpg
Điều này tốt hơn việc tự ghép chuỗi bằng tay:

folder + "/" + filename
vì Windows và macOS/Linux có cách biểu diễn đường dẫn khác nhau.

Khoan! Đừng chạy ngay code đổi tên hàng loạt 
Dù rất phấn khích, muốn "bắt tay" vào hành động thì cũng nên bình tĩnh!
Khi code chỉ:

print(filename)
thì sai cũng chẳng sao.

Nhưng:

os.rename(...)
là thao tác thật lên file.

Nếu code sai:

  • ảnh A → tên mới
  • ảnh B → tên mới
  • ảnh C → tên mới
  • ...
Bạn có thể tạo ra một mớ hỗn độn.

Vì vậy, khi viết automation:
Test bằng print() trước.

Cách an toàn hơn: In ra trước khi đổi
Thay vì:
os.rename(old_path, new_path)

hãy thử:
print(old_path, "→", new_path)

Ví dụ:

import os

folder = "photos"

files = os.listdir(folder)

for i, filename in enumerate(files, start=1):
    old_path = os.path.join(folder, filename)
    new_name = f"photo_{i:03d}.jpg"
    new_path = os.path.join(folder, new_name)

    print(old_path, "→", new_path)


Kết quả:

  • photos/IMG_8237.jpg → photos/photo_001.jpg
  • photos/DSC_00482.jpg → photos/photo_002.jpg
  • photos/photo-final.jpg → photos/photo_003.jpg
Bạn nhìn.
Kiểm tra.
Thấy đúng.

Sau đó mới bật os.rename().

Đây là tư duy debug cực kỳ quan trọng.

Chỉ đổi tên file .jpg
Bạn không muốn Python đổi cả:

  • README.txt
  • data.csv
  • main.py
Bạn chỉ muốn xử lý:

  • .jpg
Có thể kiểm tra:

if filename.lower().endswith(".jpg"):

Ví dụ:

import os

folder = "photos"

files = os.listdir(folder)

for i, filename in enumerate(files, start=1):
    if filename.lower().endswith(".jpg"):
        print(filename)


Python chỉ xử lý file JPG.

Giữ nguyên phần mở rộng của file


Giả sử thư mục có:

  • photo1.jpg
  • photo2.png
  • photo3.jpeg
Nếu bạn viết:

new_name = f"image_{i}.jpg"

thì bạn đang ép tất cả thành .jpg.

Không tốt.

Nếu muốn giữ extension cũ, có thể dùng:

name, ext = os.path.splitext(filename)

Ví dụ:

photo1.jpg
sẽ tách thành:

name = photo1
ext = .jpg
Sau đó:

new_name = f"image_{i:03d}{ext}"

Kết quả:

  • photo1.jpg → image_001.jpg
  • photo2.png → image_002.png
  • photo3.jpeg → image_003.jpeg

Một chương trình thực tế hơn
Đây là phiên bản khá dễ hiểu để "thí nghiệm":

import os

folder = "photos"

files = os.listdir(folder)

count = 1

for filename in files:
    old_path = os.path.join(folder, filename)

    if os.path.isfile(old_path):
        name, ext = os.path.splitext(filename)

        new_name = f"image_{count:03d}{ext}"
        new_path = os.path.join(folder, new_name)

        print(filename, "→", new_name)

        count += 1


Chú ý:

Ở phiên bản này chúng ta chưa gọi os.rename().

Chỉ:

print(...)
để kiểm tra.

Sau khi chắc chắn:

print(filename, "→", new_name)
đúng rồi, mới thay bằng:

os.rename(old_path, new_path)

Nhưng có một cái bẫy lớn: tên mới có thể trùng 
Giả sử thư mục đã có:

image_001.jpg
Bạn chạy script và Python muốn đổi một file khác thành:

image_001.jpg
Đây có thể gây lỗi hoặc tạo hành vi không như bạn mong muốn tùy hệ điều hành và tình huống.

Vì vậy:

Automation liên quan tới file luôn phải nghĩ tới chuyện tên mới đã tồn tại chưa.

Có thể kiểm tra:

if os.path.exists(new_path):
    print("Tên file đã tồn tại:", new_path)
else:
    os.rename(old_path, new_path)

Một nguyên tắc rất đáng nhớ: Đừng "tin" dữ liệu đầu vào
File trong thư mục có thể:
  • tên rất lạ
  • có khoảng trắng
  • có ký tự đặc biệt
  • có extension viết hoa
  • đã tồn tại tên mới
  • không phải file mà là thư mục
Cho nên automation tốt không phải:

"Code chạy được là xong."

Mà là:
Code chạy được + kiểm tra các tình huống có thể xảy ra.

Đây chính là khác biệt giữa:
"Viết được Python."

và:
"Bắt đầu biết làm project thực tế."

pathlib – cách hiện đại hơn
Ngoài os, Python còn có:

pathlib

Ví dụ:

from pathlib import Path
file = Path("old.txt")
file.rename("new.txt")


Cách này khá dễ đọc.

Làm việc với thư mục:

from pathlib import Path

folder = Path("photos")

for file in folder.iterdir():
    print(file)


pathlib rất đáng học khi làm việc với file và thư mục.

Nhưng với người mới, hiểu:

os.rename()
os.listdir()
os.path.join()
trước cũng hoàn toàn ổn.

Không cần học cả hai cùng lúc rồi tự làm mình rối. 

Python đang bắt đầu "làm việc" thay bạn
Hãy nhìn lại.

Bài đọc CSV:

CSV
↓
Đọc dữ liệu
Bài đổi tên file:

Files
↓
Đọc danh sách file
↓
Đổi tên
Đây là một bước chuyển quan trọng.

Python không còn chỉ:

print("Hello World")
nữa.

Nó bắt đầu:

Nhìn vào thư mục
↓
Tìm file
↓
Kiểm tra file
↓
Đổi tên file
Bạn đang bắt đầu dùng Python như một công cụ tự động hóa.

Ví dụ thực tế: Đổi tên tài liệu
Giả sử thư mục có:

  • document1.pdf
  • document2.pdf
  • document3.pdf
  • ...
  • document100.pdf
Bạn muốn đổi thành:

  • invoice_001.pdf
  • invoice_002.pdf
  • invoice_003.pdf
  • ...
  • invoice_100.pdf
Thay vì cần mẫn ngồi gõ:

  • F2
  • gõ
  • Enter
  • F2
  • gõ
  • Enter
  • ...
Python có thể xử lý.

Đây chính là kiểu công việc mà automation sinh ra để làm.

Ví dụ thực tế: Đổi tên file tải về
Bạn thường xuyên tải file về và nhận:

  • download
  • download (1)
  • download (2)
  • download (3)
  • download (4)


Sau đó bạn muốn:

  • report_001.pdf
  • report_002.pdf
  • report_003.pdf
  • report_004.pdf
Nếu có 5 file:

Làm tay được.

Nếu có 500 file và nếu bạn quá...rảnh thì xin mời tiếp tục, nếu không chỉ cần đọc thần chú:

Python ơi, mở cửa ra.... 

Một điều rất quan trọng: Luôn nhớ backup trước khi chạy
Đây là lời khuyên dành cho mọi thứ chứ không riêng gì đổi tên file.

Nếu bạn thử script đổi tên file lần đầu:

Hãy thử trên một thư mục test.

Ví dụ:

test_rename/
-a.txt
-b.txt
-c.txt
Đừng lần đầu tiên thử ngay trên:

Ảnh gia đình 15 năm
hoặc:

Project công ty


Automation rất mạnh.

Nhưng:

Mạnh thì cũng có thể mạnh tay, hậu quả sẽ khôn lường.

Hãy test trước.

Debug theo kiểu "chậm mà chắc"
Khi làm script đổi tên file, hãy đi theo thứ tự:

Bước 1
↓
Đọc thư mục
print(os.listdir(folder))
↓

Bước 2
↓
Chỉ lọc file cần xử lý
if filename.lower().endswith(".jpg"):
↓

Bước 3
↓
In tên cũ → tên mới
print(old_name, "→", new_name)
↓

Bước 4
↓
Kiểm tra tên mới có trùng không
↓

Bước 5
↓
Cuối cùng mới os.rename()

Đừng viết một lèo 50 dòng rồi:

"Chạy thử xem sao."

Đến lúc 500 file bị đổi sai:

"Thôi xong. Biết vậy thì....." 

Chua thêm : F2 là một hình thức "automation thủ công"
Bạn có 5 file.

Bạn:

  • F2 → gõ → Enter
  • F2 → gõ → Enter
  • F2 → gõ → Enter
  • F2 → gõ → Enter
  • F2 → gõ → Enter
Bạn "hãnh diện tự hào" gọi đó là:
"Tôi đang làm việc."

Bạn có 1.000 file.

Bạn vẫn "nghiêm túc":

  • F2 → gõ → Enter
  • F2 → gõ → Enter
  • ...
Sau 2 tiếng:

"Học Python để làm mấy việc vớ vẩn thế này sao?"

Đây chính là câu hỏi rất đúng.

Bạn học Python để những việc như vậy có thể trở thành:

python rename_files.py
Rồi ngồi uống cà phê. 

Chua thêm lần 2 : Python không cần nghỉ giải lao
Bạn:
"Đổi 500 file chắc mất cả buổi."

Python:
"500 thôi hả?"

Bạn:
"Ừ, 500 mà thôi hả trời, là rất nhiều đó cha nội!"

Python:
"Cho chương trình chạy đi."

Bạn:
"..."

Python:
"Xong."



Nhưng nhớ:
Python làm nhanh không có nghĩa Python luôn làm đúng.

Đây là lý do chúng ta liên tục nhắc:
Test → Print → Kiểm tra → Rồi mới Rename.

Checklist chuẩn không cần chỉnh
File cơ bản
  • Biết os là gì
  • Biết os.rename()
  • Biết os.listdir()
  • Biết os.path.join()
  • Biết os.path.exists()
  • Biết os.path.isfile()
  • Biết os.path.splitext()

Python
  • Biết dùng vòng for
  • Biết enumerate()
  • Biết f-string
  • Hiểu {i:02d}
  • Biết {i:03d}

Debug
  • Biết kiểm tra thư mục hiện tại
  • Biết xử lý FileNotFoundError
  • Biết kiểm tra file tồn tại
  • Biết kiểm tra tên mới bị trùng
  • Biết test bằng print() trước khi thay đổi file thật

An toàn
  • Test trên thư mục riêng
  • Backup dữ liệu quan trọng
  • Không chạy script "mù" trên thư mục thật
  • Kiểm tra kết quả trước khi xử lý hàng loạt

FAQ nhanh
Python có thể đổi tên file thật không?
Có.

Ví dụ:
os.rename("old.txt", "new.txt")

Có cần cài package không?
Không.

os là module có sẵn trong Python.

Python có đổi được hàng trăm file không?
Có.

Đó chính là một trong những trường hợp automation rất hữu ích.

Nếu đổi tên sai thì sao?
Có thể rất phiền.

Vì vậy:
Luôn test trên thư mục mẫu trước.
Đặc biệt với dữ liệu quan trọng.

os hay pathlib tốt hơn?
Cả hai đều hữu ích.

pathlib là cách hiện đại và thường dễ đọc khi làm việc với đường dẫn.
Nhưng os rất phù hợp để người mới hiểu những thao tác cơ bản.

Có thể đổi cả phần mở rộng không?
Có.

Nhưng phải cực kỳ cẩn thận.

Đổi:

file.txt
thành:

file.jpg
không biến nội dung file text thành hình ảnh.

Đổi tên extension không đồng nghĩa với chuyển đổi định dạng file.

Đây là hai chuyện hoàn toàn khác nhau.

Tóm lại
Hôm nay chúng ta không thảo luận một thứ gì quá "cao siêu", quá "hàn lâm".

Chúng ta chỉ làm việc đơn giản:
Đổi tên file.

Nhưng phía sau nó là rất nhiều tư duy quan trọng:
Python
 ↓
Làm việc với hệ điều hành
 ↓
Đọc thư mục
 ↓
Tìm file
 ↓
Kiểm tra
 ↓
Xử lý
 ↓
Thay đổi hàng loạt

Bạn đã đi từ:
print("Hello")

đến:
os.rename(...)

Nghe nhỏ thôi.

Nhưng đây là một bước rất quan trọng.

Bởi vì lập trình thực tế không phải lúc nào cũng là:
"Viết một thuật toán thật hoành tráng."

Rất nhiều khi nó chỉ là:
Có một công việc nhàm chán phải làm 500 lần → viết code để máy làm.

Và đó chính là:
Automation.