Python cho học sinh: tự làm tool dọn file và đổi tên hàng loạt trong 45 phút, không cần cài thêm thư viện
Thư mục Downloads của bạn có đang giống một cái ngăn kéo lộn xộn không: ảnh, bài tập Word, video, file code nằm chung một chỗ, tên file thì IMG_8392, IMG_8395, không biết cái nào là cái nào? Bài này không dạy lý thuyết Python dài dòng. Bạn sẽ làm ra một công cụ thật, chạy được ngay, và dùng được cho chính thư mục đó — nhưng theo cách an toàn: xem trước rồi mới dọn thật.
Quyết định nhanh trước khi đọc tiếp: nếu bạn chỉ muốn dọn thư mục cho gọn, làm phần 1. Nếu bạn hay phải nộp ảnh, bài tập theo tên có thứ tự như anh-du-lich_01.jpg , làm thêm phần 2. Cả hai đều nằm trong cùng một file code, không cần cài thêm thư viện nào.
Tóm tắt trong 30 giây
Làm gì: một tool Python dọn file theo đuôi file (ảnh, tài liệu, video, code) và đổi tên hàng loạt theo mẫu có số thứ tự.
Thời gian: khoảng 45 phút, tính cả lúc thử trên thư mục mẫu.
Trình độ: đã biết biến, vòng lặp, hàm và chạy file Python trong terminal. Chưa biết cũng làm được nếu làm đúng từng bước, vì code đã có sẵn và giải thích ngay bên dưới.
Cần gì: Python 3.10 trở lên, một trình soạn code bất kỳ (VS Code, hoặc Notepad cũng được), không cần cài thêm thư viện.
Kết quả: một file organizer.py chạy được bằng 2 lệnh, có chế độ xem trước để bạn kiểm tra trước khi file bị di chuyển thật.
An toàn trước khi chạy: 3 quy tắc không được bỏ qua
Ảnh minh họa: nguyên tắc quan trọng nhất của bài này là xem trước rồi mới dọn thật. Ảnh trong bài là minh họa, phần làm thật nằm ở code và lệnh bên dưới — bạn copy code, không copy ảnh.
Thử trên thư mục mẫu trước. Tạo một thư mục test_files và copy vài file không quan trọng vào đó. Chỉ khi nào chạy đúng trên thư mục mẫu, bạn mới dùng cho thư mục thật.
Luôn chạy xem trước trước. Tool này mặc định chỉ in ra kế hoạch, chưa di chuyển file nào. Chỉ khi bạn thêm --go , file mới bị di chuyển hoặc đổi tên thật.
Đừng chạy vào thư mục hệ thống, ổ C, hay thư mục gốc chứa tài liệu quan trọng mà chưa sao lưu. Và đừng chạy khi file đang mở trong Word hay phần mềm khác, vì file đang mở có thể báo lỗi quyền truy cập.
Bước 1: Kiểm tra Python đã có chưa
Mở terminal (trên Windows là Command Prompt hoặc PowerShell, trên Mac là Terminal) và gõ:
python3 --version
Nếu máy in ra dạng Python 3.11.0 hoặc cao hơn, bạn làm tiếp. Nếu máy báo không tìm thấy lệnh, thử gõ python --version . Nếu cả hai đều không được, bạn cần cài Python từ python.org trước, rồi quay lại bài này.
Bước 2: Chuẩn bị thư mục mẫu
Tạo một thư mục mới tên test_files ở cùng chỗ với file code sắp tạo, rồi copy vào đó vài file mẫu, ví dụ: một ảnh, một file Word, một video, một file code, một file ghi chú. Đừng dùng file thật quan trọng ở bước này. Cấu trúc lúc bắt đầu sẽ giống như sau:
test_files/ anh1.JPG bao-cao.docx video.mp4 code.py ghi-chu.txt
Lưu ý nhỏ nhưng quan trọng: file ảnh trong ví dụ cố tình để đuôi viết hoa là .JPG . Tool dưới đây xử lý được trường hợp này vì nó chuyển đuôi file về chữ thường trước khi so sánh.
Bước 3: Lưu code đầy đủ của tool
Tạo file mới tên organizer.py , copy toàn bộ code dưới đây vào và lưu lại. Đây là code đã được chạy thử thật, không phải code minh họa:
"""Tool don file va doi ten hang loat - chi dung thu vien co san cua Python.""" import argparse import shutil from pathlib import Path FOLDERS = { "Anh": {".jpg", ".jpeg", ".png", ".gif", ".webp", ".heic"}, "TaiLieu": {".pdf", ".docx", ".doc", ".txt", ".pptx", ".xlsx"}, "Video": {".mp4", ".mov", ".mkv", ".avi"}, "AmThanh": {".mp3", ".wav", ".m4a"}, "Code": {".py", ".html", ".css", ".js"}, } def get_category(file_path): suffix = file_path.suffix.lower() for category, extensions in FOLDERS.items(): if suffix in extensions: return category return "Khac" def unique_path(destination): if not destination.exists(): return destination counter = 1 while True: new_path = destination.with_name( f"{destination.stem}_{counter}{destination.suffix}" ) if not new_path.exists(): return new_path counter += 1 def organize(folder, dry_run): for file_path in sorted(folder.iterdir()): if not file_path.is_file(): continue if file_path.name == Path(__file__).name: continue category = get_category(file_path) target = unique_path(folder / category / file_path.name) print(f"{file_path.name} -> {target.parent.name}/{target.name}") if not dry_run: target.parent.mkdir(exist_ok=True) shutil.move(str(file_path), str(target)) def rename_files(folder, prefix, dry_run): files = [p for p in sorted(folder.iterdir()) if p.is_file()] for index, file_path in enumerate(files, start=1): new_name = f"{prefix}_{index:02d}{file_path.suffix.lower()}" target = folder / new_name if target == file_path: continue if target.exists(): print(f"BO QUA {file_path.name}: {new_name} da ton tai") continue print(f"{file_path.name} -> {new_name}") if not dry_run: file_path.rename(target) def main(): parser = argparse.ArgumentParser(description="Don file va doi ten hang loat") parser.add_argument("folder", help="Thu muc can don, vi du: test_files") parser.add_argument("--go", action="store_true", help="Chay that. Khong co --go thi chi xem truoc.") parser.add_argument("--rename", metavar="TIEN_TO", help="Doi ten file thanh TIEN_TO_01, TIEN_TO_02, ...") args = parser.parse_args() folder = Path(args.folder) if not folder.is_dir(): print(f"Khong tim thay thu muc: {folder}") return dry_run = not args.go if dry_run: print("CHE DO XEM TRUOC - chua di chuyen hay doi ten file nao.") if args.rename: rename_files(folder, args.rename, dry_run) else: organize(folder, dry_run) if __name__ == "__main__": main()
Code này làm gì, đọc theo từng khối:
FOLDERS là một từ điển: đuôi file nào thì vào thư mục nào. Muốn thêm loại file mới, bạn chỉ cần thêm đuôi vào đây, ví dụ thêm ".zip" vào một nhóm mới.
get_category lấy đuôi file, chuyển về chữ thường rồi tra trong từ điển. File không khớp nhóm nào sẽ vào thư mục Khac , thay vì bị bỏ sót.
unique_path xử lý trùng tên: nếu thư mục đích đã có file cùng tên, tool tự đổi thành _1 , _2 thay vì ghi đè lên file cũ.
organize duyệt từng file, in ra kế hoạch, và chỉ di chuyển thật khi không ở chế độ xem trước.
rename_files đánh số từ 01 trở đi theo thứ tự tên file. Nếu tên mới đã tồn tại, nó bỏ qua file đó và in ra cảnh báo, thay vì ghi đè.
main dùng argparse để đọc lệnh từ terminal: thư mục cần dọn, có chạy thật hay không ( --go ), và có đổi tên hay không ( --rename ).
Bước 4: Chạy xem trước, rồi mới chạy thật
Đứng ở thư mục chứa file organizer.py và gõ lệnh xem trước:
python3 organizer.py test_files
Kết quả đúng sẽ giống như sau. Lưu ý dòng đầu tiên xác nhận bạn đang ở chế độ xem trước, và chưa file nào bị di chuyển:
CHE DO XEM TRUOC - chua di chuyen hay doi ten file nao. anh1.JPG -> Anh/anh1.JPG bao-cao.docx -> TaiLieu/bao-cao.docx code.py -> Code/code.py ghi-chu.txt -> TaiLieu/ghi-chu.txt video.mp4 -> Video/video.mp4
Nếu danh sách trên đúng ý bạn, chạy thật bằng cách thêm --go :
python3 organizer.py test_files --go
Sau khi chạy, thư mục của bạn sẽ gọn lại thành:
test_files/ Anh/anh1.JPG TaiLieu/bao-cao.docx TaiLieu/ghi-chu.txt Video/video.mp4 Code/code.py
Nếu bạn mở lại thư mục và thấy file “biến mất”, đừng hoảng: file không bị xóa, nó chỉ được chuyển vào thư mục con tương ứng. Đó cũng là lý do bước xem trước quan trọng — bạn biết trước file sẽ đi đâu.
Bước 5: Đổi tên hàng loạt theo mẫu có số thứ tự
Ảnh minh họa: đổi tên hàng loạt không phải là gõ lại từng tên, mà là áp một mẫu chung — tiền tố cộng số thứ tự — cho cả thư mục.
Tạo một thư mục mẫu khác, ví dụ test_rename , chứa các ảnh tên lộn xộn như IMG_8392.jpg , IMG_8395.jpg , IMG_8401.jpg . Chạy xem trước:
python3 organizer.py test_rename --rename anh-du-lich
CHE DO XEM TRUOC - chua di chuyen hay doi ten file nao. IMG_8392.jpg -> anh-du-lich_01.jpg IMG_8395.jpg -> anh-du-lich_02.jpg IMG_8401.jpg -> anh-du-lich_03.jpg
Đúng ý rồi thì chạy thật:
python3 organizer.py test_rename --rename anh-du-lich --go
Thứ tự đánh số dựa trên thứ tự tên file khi sắp xếp, nên nếu bạn muốn ảnh theo đúng thứ tự chụp, hãy kiểm tra lại danh sách xem trước trước khi thêm --go . Với hơn 99 file, bạn có thể đổi 02d trong code thành 03d để số thành 001, 002, 003.
Khi gặp lỗi, kiểm tra theo thứ tự này
Báo không tìm thấy thư mục: bạn đang đứng sai thư mục trong terminal. Gõ lại lệnh từ thư mục chứa file organizer.py và thư mục test_files , hoặc ghi đường dẫn đầy đủ thay vì chỉ ghi tên thư mục.
Báo lỗi quyền truy cập khi chạy thật: thường là file đang mở trong Word, trình xem ảnh hoặc phần mềm khác. Đóng file đó rồi chạy lại.
File trùng tên: tool tự thêm _1 , _2 khi dọn file, và bỏ qua khi đổi tên nếu tên mới đã tồn tại. Đừng sửa tay tên file giữa chừng rồi chạy lại ngay, vì thứ tự đánh số có thể thay đổi.
File không có đuôi: tool xếp vào thư mục Khac . Đó là hành vi cố tình, để bạn tự kiểm tra những file lạ thay vì tool tự đoán sai.
Chạy xong nhưng thư mục con không xuất hiện: bạn đang ở chế độ xem trước và chưa thêm --go . Chạy lại lệnh với --go ở cuối.
3 cách nâng cấp tiếp theo, mỗi cách là một bài học mới
Thêm nhóm file của riêng bạn: thêm đuôi .zip , .psd hoặc tên thư mục bạn muốn vào từ điển FOLDERS . Đây là cách nhanh nhất để hiểu từ điển trong Python có tác dụng thật như thế nào.
Ghi lại nhật ký dọn file: thay vì chỉ in ra màn hình, ghi mỗi dòng tên cũ -> tên mới vào một file log.txt . Khi đó bạn có thể đối chiếu sau này nếu cần tìm lại file cũ.
Làm giao diện bấm nút: khi đã quen với bản terminal, bạn có thể bọc tool này bằng Tkinter để chọn thư mục bằng cửa sổ thay vì gõ lệnh. Đó là bước tự nhiên tiếp theo trước khi làm các tool có giao diện thật.
Kết luận: một tool nhỏ, nhưng là một chương trình thật
Điểm khác biệt giữa “học Python” và “dùng Python” nằm ở chỗ này: cuối buổi, bạn không chỉ có thêm một đoạn code chép trong vở, mà có một file organizer.py chạy được, dọn được thư mục thật, và có chế độ xem trước để không làm mất file. Hãy giữ file này lại, dùng nó mỗi tuần cho thư mục Downloads, và mỗi lần muốn thêm tính năng, bạn sẽ học thêm một khái niệm mới vì bạn cần nó — không phải vì sách bảo học.
Trong series này, các bài tiếp theo sẽ đi theo cùng một kiểu: một tool dùng được ngay cho việc học và sinh hoạt của học sinh, code đầy đủ và chạy thử thật, không dừng ở mức ý tưởng. Hai hướng tiếp theo được nhiều người học Python nhắc tới nhất là làm app nhắc học Pomodoro có lưu tiến độ, và làm tool tạo mã QR cho bài thuyết trình — bạn có thể bắt đầu từ hướng nào cũng được, vì cả hai đều dùng lại đúng cách tổ chức code như bài này: chia hàm nhỏ, xem trước trước khi thay đổi thật, và xử lý trường hợp file đã tồn tại.