Đổi tên file thông thường hay đổi tên ảnh hàng loạt luôn là công việc dễ "nản Chí Phèo" nhất, một công việc mà bất cứ ai đã từng làm thủ công cũng đều "thề" rằng không bao giờ thèm làm lại lần thứ hai!
Có một ngày bạn mở thư mục ảnh lên và thấy:IMG_8237.jpg
IMG_8238.jpg
IMG_8239.jpg
DSC_00482.jpg
DSC_00483.jpg
photo_20260715_091233.jpg
Screenshot_20260715_102233.pngNhìn vào thì biết ngay:
"Đây là ảnh."
Nhưng nhìn tên file thì...
"Ảnh gì? Của ai? Chụp cái gì? Ngày nào?"
Không biết. 😅
Nếu chỉ có 3–5 tấm thì thôi.
Click → F2 → đổi tên → Enter.
Lặp lại vài lần cũng chưa đến mức muốn đập bàn.
Nhưng nếu có:
100 ảnh
500 ảnh
1.000 ảnhthì việc ngồi đổi tên từng ảnh bắt đầu trở thành một công việc rất... không đáng để con người làm.
Và đây chính là lúc Python có thể giúp.
Đổi tên ảnh bằng Python là gì?
Thật ra, nếu bạn đã đọc Bài Đổi tên file hàng loạt bằng Python, thì bài này không phải một thế giới hoàn toàn mới.
Ảnh cũng chỉ là file.
Ví dụ:
IMG_8237.jpgvẫn là một file có:
- tên:
IMG_8237 - phần mở rộng:
.jpg
Python không cần phải "nhìn thấy" nội dung bức ảnh mới đổi được tên.
Nó chỉ cần biết:
"File này đang nằm ở đâu và tên hiện tại của nó là gì?"
Sau đó Python có thể nói:
"Được rồi, đổi tên đi."
Một ví dụ rất đời thường
Giả sử bạn vừa chụp 5 tấm ảnh ở Sơn Trà Đà Nẵng.
Điện thoại đặt tên:
IMG_8237.jpg
IMG_8238.jpg
IMG_8239.jpg
IMG_8240.jpg
IMG_8241.jpgBạn muốn đổi thành:
sontra_001.jpg
sontra_002.jpg
sontra_003.jpg
sontra_004.jpg
sontra_005.jpgNếu làm bằng tay:
F2
F2
F2
F2
F25 tấm thì còn được.
Nhưng nếu có 500 tấm:
F2
F2
F2
F2
...Đến tấm thứ 200 có khi bạn bắt đầu tự hỏi:
"Mình học Python để làm gì vậy ta?" 😂
Câu trả lời chính là:
Để không phải F2 500 lần.
Python có thể đổi tên ảnh như thế nào?
Cách đơn giản nhất vẫn là dùng module os.
Ví dụ:
import os
os.rename("IMG_8237.jpg", "sontra_001.jpg")Xong.
Python sẽ đổi:
IMG_8237.jpgthành:
sontra_001.jpgKhông cần mở Photoshop.
Không cần mở Lightroom.
Không cần click chuột 500 lần.
Nhưng ảnh thường nằm trong một thư mục
Ví dụ cấu trúc thư mục:
project/
│
├── rename_images.py
│
└── photos/
├── IMG_8237.jpg
├── IMG_8238.jpg
├── IMG_8239.jpg
└── IMG_8240.jpgKhi đó:
import os
os.rename(
"photos/IMG_8237.jpg",
"photos/sontra_001.jpg"
)Python sẽ đổi tên file bên trong thư mục photos.
Đổi tên hàng loạt mới là phần thú vị 😎
Giả sử thư mục có:
IMG_8237.jpg
IMG_8238.jpg
IMG_8239.jpg
IMG_8240.jpg
IMG_8241.jpgTa có thể dùng vòng lặp:
import os
for i in range(1, 6):
old_name = f"IMG_{8236 + i}.jpg"
new_name = f"sontra_{i:03d}.jpg"
os.rename(
f"photos/{old_name}",
f"photos/{new_name}"
)Kết quả:
sontra_001.jpg
sontra_002.jpg
sontra_003.jpg
sontra_004.jpg
sontra_005.jpg{i:03d} là cái gì vậy?
Nhìn hơi giống mật mã nhưng thật ra rất đơn giản.
Nếu:
i = 1thì:
f"{i:03d}"cho kết quả:
001Nếu:
i = 12thì:
012Nếu:
i = 125thì:
125Tức là luôn cố gắng giữ 3 chữ số.
Vì vậy:
f"sontra_{i:03d}.jpg"sẽ tạo:
sontra_001.jpg
sontra_002.jpg
sontra_003.jpg
...
sontra_099.jpg
sontra_100.jpgCách đặt tên này nhìn gọn hơn rất nhiều so với:
sontra_1.jpg
sontra_2.jpg
sontra_10.jpg
sontra_100.jpgNhưng có một vấn đề...
Ảnh ngoài đời đâu có ngoan như ví dụ.
Thư mục thực tế có thể là:
IMG_8237.jpg
IMG_8238.JPG
IMG_8239.jpeg
DSC_0012.jpg
photo.png
logo.webp
document.pdf
video.mp4Lúc này nếu chúng ta viết:
for file in os.listdir("photos"):
...thì Python sẽ nhìn thấy tất cả.
Cả:
.jpg
.png
.webp
.pdf
.mp4Chúng ta chỉ muốn xử lý ảnh.
Vậy phải lọc.
Lọc những file là ảnh
Ta có thể kiểm tra phần mở rộng:
import os
image_extensions = (".jpg", ".jpeg", ".png", ".webp")
for file in os.listdir("photos"):
if file.lower().endswith(image_extensions):
print(file)Kết quả có thể là:
IMG_8237.jpg
IMG_8238.JPG
IMG_8239.jpeg
photo.png
logo.webpCòn:
document.pdf
video.mp4sẽ bị bỏ qua.
Tại sao phải dùng .lower()?
Hãy nhìn hai file:
photo.jpg
photo.JPGVới con người:
"Ừ, đều là JPG."
Nhưng khi xử lý chuỗi, Python phân biệt chữ hoa và chữ thường.
Nếu viết:
file.endswith(".jpg")thì:
photo.jpgđược nhận.
Nhưng:
photo.JPGcó thể không được nhận.
Vì vậy:
file.lower().endswith(".jpg")sẽ biến:
photo.JPGthành:
photo.jpgrồi mới kiểm tra.
An toàn hơn.
Đừng quên giữ lại phần mở rộng
Đây là một lỗi người mới rất dễ mắc.
Ví dụ file:
IMG_8237.jpgBạn muốn đổi thành:
sontra_001.jpgNhưng nếu vô tình tạo:
sontra_001thì bạn đã bỏ mất .jpg.
Trong trường hợp đổi tên ảnh hàng loạt, tốt nhất là:
Đổi phần tên, nhưng giữ nguyên phần mở rộng.
Python có thể giúp chúng ta làm việc này bằng:
os.path.splitext()Ví dụ:
name, extension = os.path.splitext("IMG_8237.jpg")
print(name)
print(extension)Kết quả:
IMG_8237
.jpgSau đó:
new_name = "sontra_001" + extensionsẽ thành:
sontra_001.jpgVí dụ thực tế hơn
Giả sử thư mục:
photos/
├── IMG_8237.jpg
├── IMG_8238.JPG
├── DSC_0012.jpeg
├── photo.png
└── document.pdfTa muốn đổi tên tất cả ảnh thành:
sontra_001.jpg
sontra_002.JPG
sontra_003.jpeg
sontra_004.pngCó thể viết:
import os
folder = "photos"
image_extensions = (".jpg", ".jpeg", ".png", ".webp")
counter = 1
for file in os.listdir(folder):
if file.lower().endswith(image_extensions):
old_path = os.path.join(folder, file)
name, extension = os.path.splitext(file)
new_name = f"sontra_{counter:03d}{extension}"
new_path = os.path.join(folder, new_name)
print(old_path, "->", new_path)
counter += 1Chú ý:
Chương trình này chưa đổi tên thật.
Nó chỉ:
print(...)để chúng ta xem Python định làm gì.
Đây là một thói quen rất đáng có.
Test trước, đổi tên sau
Đây là nguyên tắc mình rất khuyến khích khi làm việc với file:
Đừng cho Python làm thật ngay lần đầu.
Trước tiên:
print(old_path, "->", new_path)Chạy thử.
Nếu thấy:
photos/IMG_8237.jpg -> photos/sontra_001.jpg
photos/IMG_8238.JPG -> photos/sontra_002.JPG
photos/DSC_0012.jpeg -> photos/sontra_003.jpegvà mọi thứ đúng như mong muốn...
Lúc đó mới đổi:
print(old_path, "->", new_path)thành:
os.rename(old_path, new_path)Đây là khác biệt giữa:
"Mình nghĩ code chạy đúng."
và:
"Mình đã kiểm tra code trước khi cho nó đụng vào dữ liệu thật."
Một lỗi rất đáng sợ: tên mới đã tồn tại
Giả sử thư mục đã có:
sontra_001.jpgNhưng Python lại muốn đổi:
IMG_8237.jpgthành:
sontra_001.jpgBạn không nên mặc định rằng:
"Python tự xử lý được hết."
Hãy kiểm tra trước:
if os.path.exists(new_path):
print("Tên file đã tồn tại:", new_path)
else:
os.rename(old_path, new_path)Cách này giúp tránh những tình huống đổi tên không như mong muốn.
Một phiên bản hoàn chỉnh, dễ hiểu
Đây là phiên bản phù hợp để bạn thử trên một thư mục ảnh mẫu:
import os
folder = "photos"
image_extensions = (".jpg", ".jpeg", ".png", ".webp")
counter = 1
for file in os.listdir(folder):
if not file.lower().endswith(image_extensions):
continue
old_path = os.path.join(folder, file)
name, extension = os.path.splitext(file)
new_name = f"sontra_{counter:03d}{extension}"
new_path = os.path.join(folder, new_name)
if os.path.exists(new_path):
print("Bỏ qua vì tên đã tồn tại:", new_path)
continue
print(f"{file} -> {new_name}")
os.rename(old_path, new_path)
counter += 1Chương trình làm lần lượt:
Bước 1
Mở thư mục:
folder = "photos"Bước 2
Lấy danh sách file:
os.listdir(folder)Bước 3
Chỉ giữ lại file ảnh:
if not file.lower().endswith(image_extensions):
continueBước 4
Tách tên và phần mở rộng:
name, extension = os.path.splitext(file)Bước 5
Tạo tên mới:
new_name = f"sontra_{counter:03d}{extension}"Bước 6
Tạo đường dẫn đầy đủ:
new_path = os.path.join(folder, new_name)Bước 7
Kiểm tra tên mới có tồn tại không:
if os.path.exists(new_path):
continueBước 8
Đổi tên:
os.rename(old_path, new_path)Nhưng có một chuyện cần nhớ: thứ tự file
Đây là chỗ có thể khiến người mới hơi bất ngờ.
Bạn có:
IMG_100.jpg
IMG_20.jpg
IMG_3.jpgPython không nhất thiết hiểu rằng:
3
20
100là thứ tự bạn đang nghĩ.
Nếu muốn chủ động hơn, có thể lấy danh sách ảnh rồi sắp xếp:
files = []
for file in os.listdir(folder):
if file.lower().endswith(image_extensions):
files.append(file)
files.sort()Sau đó mới đổi tên.
Ví dụ:
files.sort()
for counter, file in enumerate(files, start=1):
...enumerate() giúp chúng ta vừa lấy file vừa có số thứ tự.
Tại sao nên đổi tên ảnh có quy tắc?
Một thư mục như:
IMG_8237.jpg
DSC_0012.jpg
photo_abc.jpg
final-final-2.jpg
newnew.jpg
abc123.jpgrất khó quản lý.
Nhưng:
sontra_001.jpg
sontra_002.jpg
sontra_003.jpg
sontra_004.jpg
sontra_005.jpgthì dễ nhìn hơn rất nhiều.
Đặc biệt khi làm website.
Ví dụ:
product_001.jpg
product_002.jpg
product_003.jpghoặc:
danang_001.jpg
danang_002.jpg
danang_003.jpgTên file rõ ràng cũng giúp con người quản lý dữ liệu dễ hơn.
Nếu có hàng nghìn ảnh thì sao?
Đây mới là lúc Python bắt đầu "đi làm".
Ví dụ bạn có:
2.000 ảnh sản phẩmvà muốn:
product_0001.jpg
product_0002.jpg
product_0003.jpg
...
product_2000.jpgBạn không cần viết 2.000 dòng code.
Chỉ cần vòng lặp.
Ví dụ:
for i, file in enumerate(files, start=1):
print(f"{file} -> product_{i:04d}.jpg")04d nghĩa là giữ 4 chữ số:
0001
0002
0003
...
0099
0100
1000Python làm phần lặp.
Bạn chỉ cần nói quy tắc.
Đây chính là tư duy automation:
Con người đặt luật. Máy làm phần lặp lại.
Đổi tên ảnh không có nghĩa là Python phải hiểu nội dung ảnh
Đây là một điểm rất quan trọng.
Khi chúng ta viết:
os.rename(...)Python chỉ đang xử lý file.
Nó không biết:
"À, trong ảnh này có con mèo."
Hay:
"Đây là ảnh biển Sơn Trà lúc hoàng hôn."
Muốn Python:
- đọc ảnh,
- thay đổi kích thước,
- nén ảnh,
- nhận diện khuôn mặt,
- nhận diện vật thể,
- thêm watermark,
thì đó là những bài toán khác.
Có thể cần thêm thư viện như Pillow hoặc các công cụ AI/computer vision.
Nhưng Bài #71 chỉ tập trung vào đổi tên ảnh.
Đừng thấy chữ "ảnh" rồi lập tức kéo cả AI vào. 😄
Một lỗi kinh điển: chạy nhầm thư mục
Bạn chạy:
os.listdir("photos")nhưng Python báo:
FileNotFoundErrorĐừng vội kết luận:
"Python bị điên."
Hãy kiểm tra thư mục hiện tại:
import os
print(os.getcwd())Python sẽ cho biết chương trình đang chạy ở đâu.
Ví dụ:
C:\Users\Monkey\Desktop\python-projectNếu thư mục thật sự nằm ở:
C:\Users\Monkey\Desktop\python-project\photosthì:
folder = "photos"là hợp lý.
Nhưng nếu thư mục nằm chỗ khác thì phải sửa đường dẫn.
Có thể dùng đường dẫn đầy đủ không?
Có.
Ví dụ Windows:
folder = r"C:\Users\Monkey\Pictures\SonTra"Chữ r phía trước chuỗi giúp Python xử lý đường dẫn Windows dễ hơn.
Hoặc dùng /:
folder = "C:/Users/Monkey/Pictures/SonTra"Cả hai cách đều có thể hữu ích.
Đừng thử ngay trên thư mục 2.000 ảnh
Đây là lời khuyên thật lòng. 😅
Nếu mới học, hãy tạo:
test_photos/bên trong chỉ có:
IMG_1.jpg
IMG_2.jpg
IMG_3.jpg
IMG_4.jpg
IMG_5.jpgChạy thử.
Nếu đúng:
sontra_001.jpg
sontra_002.jpg
sontra_003.jpg
sontra_004.jpg
sontra_005.jpgthì hãy nghĩ đến thư mục thật.
Và nếu dữ liệu quan trọng:
Backup trước khi chạy script.
Một dòng:
os.rename(...)trông rất hiền.
Nhưng nếu logic sai thì 2.000 file cũng bị đổi tên rất nhanh.
Python không biết tiếc đâu. 😂
Chua thêm 😭
Có những người nhìn thư mục:
IMG_0001.jpg
IMG_0002.jpg
IMG_0003.jpg
...
IMG_0500.jpgrồi nói:
"Để cuối tuần rảnh mình đổi tên."
Cuối tuần đến:
"Thôi để tuần sau."
Tuần sau:
"Thôi để khi nào cần."
Đến lúc cần tìm:
"Ủa ảnh cái này tên gì ta?"
Mở Google:
"Làm sao đổi tên 500 files."
Rồi cài một phần mềm.
Trong khi Python ngồi một góc:
os.rename(...)và nhìn bạn:
"Gọi tôi từ đầu có phải đỡ khổ không?" 😭
Một tư duy quan trọng hơn cả đoạn code
Bài này không chỉ dạy bạn:
os.rename()Mà quan trọng hơn là dạy một cách suy nghĩ.
Khi gặp một công việc lặp lại, hãy tự hỏi:
"Việc này có quy luật không?"
Ví dụ:
ảnh 1 → sontra_001
ảnh 2 → sontra_002
ảnh 3 → sontra_003
...Có quy luật.
Vậy máy tính có thể làm.
Đây chính là nền móng của Automation.
Sau này quy mô lớn hơn:
đổi tên file
↓
đọc file
↓
lọc dữ liệu
↓
xử lý dữ liệu
↓
lấy dữ liệu từ website
↓
lưu dữ liệu
↓
gửi email
↓
tạo báo cáoBạn sẽ bắt đầu nhận ra:
"À... Python không chỉ để làm bài tập."
Python có thể làm những công việc mà trước đây mình ngồi click chuột cả buổi.
Checklist trước khi chạy chương trình đổi tên ảnh
☑ Xác định đúng thư mục ảnh.
☑ Kiểm tra os.getcwd() nếu đường dẫn có vấn đề.
☑ Chỉ lọc những phần mở rộng cần thiết:
(".jpg", ".jpeg", ".png", ".webp")☑ Dùng .lower() để tránh vấn đề .JPG / .jpg.
☑ Giữ lại phần mở rộng của ảnh.
☑ Kiểm tra tên mới có bị trùng.
☑ Dùng print() để xem trước kết quả.
☑ Thử trên 3–5 ảnh trước.
☑ Backup nếu ảnh quan trọng.
☑ Sau khi chắc chắn mới cho os.rename() chạy thật.
FAQ nhanh
1. Python có đổi được .jpg và .png cùng lúc không?
Có.
Ví dụ:
image_extensions = (".jpg", ".jpeg", ".png", ".webp")2. Đổi tên ảnh có làm giảm chất lượng ảnh không?
Không.
os.rename() chỉ đổi tên file.
Nó không chỉnh sửa nội dung ảnh.
3. Có cần cài thêm thư viện không?
Không nếu chỉ đổi tên.
os là module có sẵn trong Python.
4. Có thể đổi tên 10.000 ảnh không?
Về nguyên tắc, có.
Nhưng càng nhiều file thì càng nên:
- kiểm tra kỹ quy tắc,
- backup,
- test trên bản sao,
- xử lý trường hợp tên trùng.
Đừng biến một script 10 dòng thành một chiếc máy xay dữ liệu. 😅
5. Có nhất thiết phải dùng os không?
Không.
Python hiện đại còn có pathlib, ví dụ:
from pathlib import Pathpathlib rất đáng học.
Nhưng nếu bạn mới bắt đầu, hiểu được:
os.listdir()
os.path.join()
os.path.splitext()
os.rename()trước cũng hoàn toàn ổn.
Quan trọng là hiểu tư duy xử lý file.
Tổng kết
Trong bài này, chúng ta đã biến một việc rất thủ công:
F2
F2
F2
F2
F2
...thành một quy trình có thể tự động hóa bằng Python.
Bạn đã biết:
os.listdir()để lấy danh sách file.
os.path.splitext()để tách tên và phần mở rộng.
os.path.join()để tạo đường dẫn.
os.path.exists()để kiểm tra file có tồn tại.
Và quan trọng nhất:
os.rename()để đổi tên.
Nhưng điều quan trọng nhất của bài này không phải là nhớ 4–5 hàm.
Mà là hình thành thói quen:
Thấy công việc lặp đi lặp lại → tìm quy luật → viết code → để máy làm phần lặp.
Đó chính là một trong những bước đầu tiên để chuyển từ:
"Mình biết Python."
sang:
"Mình dùng Python để giải quyết công việc thật sự."
Bạn có thể cũng đang gặp...
Nếu đang học Python từ những lỗi và công việc thực tế, bạn có thể xem lại:
- Pip không hoạt động 🐍😭
- Virtual Environment – Tại sao Python Developer lại thích tạo môi trường ảo?
- requirements.txt là gì? 📦
- Đọc CSV bằng Python 📊
- Đổi tên file hàng loạt bằng Python 📁
Những bài này ghép lại thành một mạch khá thú vị:
Cài package
↓
Tạo môi trường
↓
Quản lý dependencies
↓
Đọc dữ liệu
↓
Xử lý file
↓
Đổi tên ảnh
↓
Web Scraping
↓
AutomationVà từ đây Python bắt đầu bước ra khỏi phạm vi:
"Viết vài dòng code cho vui.", có thể là suy nghĩ khi mới bước vào Đất Việt Lập Trình?!
để tiến tới:
"Làm cho máy tính làm việc thay mình."