يمكنك إعادة تسمية مئات الملفات دفعة واحدة باستخدام بايثون عبر pathlib، بتمرير حلقة على الملفات وبناء الاسم الجديد ثم تنفيذ Path.rename(). ويمكنك في نفس السكربت ترقيم الملفات تلقائيًا، إضافة Prefix أو Suffix، استبدال جزء من الاسم، أو استهداف امتداد محدد فقط.
سنبدأ بمعاينة Dry Run قبل لمس الملفات، ثم نضيف فحصًا يمنع استخدام اسم موجود مسبقًا.
قبل التنفيذ: استخدم نسخة تجريبية من المجلد واحتفظ بنسخة احتياطية. لا تشغّل سكربت إعادة تسمية جماعية على ملفات مهمة قبل أن تراجع الأسماء الجديدة.
النتيجة التي سنصل إليها
| قبل | بعد |
|---|---|
photo_1.jpg | product_001.jpg |
photo_2.jpg | product_002.jpg |
photo_3.jpg | product_003.jpg |
إعادة تسمية ملف واحد لفهم الفكرة
pathlib موجودة ضمن مكتبة بايثون القياسية ولا تحتاج إلى تثبيت.
from pathlib import Path
old_path = Path("photo_1.jpg")
new_path = Path("product_001.jpg")
old_path.rename(new_path)
هذا يغيّر اسم ملف واحد فقط. الفكرة نفسها ستتكرر لاحقًا داخل حلقة تمر على مئات الملفات.
مسار Windows الصحيح
إذا كان المجلد مثل C:\Users\Name\Pictures فاستخدم Raw String:
from pathlib import Path
folder = Path(
r"C:\Users\Name\Pictures"
)
إعادة تسمية جميع الملفات مع ترقيم تلقائي
هذا المثال يوضح الترقيم والحفاظ على الامتداد، لكنه ينفذ التغيير فعليًا؛ استخدمه فقط على مجلد تجريبي:
from pathlib import Path
folder = Path("photos")
files = sorted(
(
file
for file in folder.iterdir()
if file.is_file()
),
key=lambda file: file.name.lower()
)
for index, file in enumerate(files, start=1):
new_name = (
f"product_{index:03d}"
f"{file.suffix}"
)
new_path = file.with_name(new_name)
file.rename(new_path)
{index:03d} ينتج 001 و002 و003. واستخدام file.suffix يحافظ على امتداد الملف الأصلي.
استخدمنا sorted() لأن ترتيب iterdir() ليس ترتيبًا يجب الاعتماد عليه عند الترقيم.
إذا كان ملف السكربت داخل المجلد وكنت تعيد تسمية كل الملفات، فقد يدخل هو نفسه ضمن العناصر المستهدفة. الأفضل وضع السكربت خارج مجلد البيانات أو فلترة الامتداد.
إعادة تسمية ملفات JPG فقط مع Dry Run
from pathlib import Path
folder = Path("photos")
jpg_files = sorted(
(
file
for file in folder.iterdir()
if (
file.is_file()
and file.suffix.lower() == ".jpg"
)
),
key=lambda file: file.name.lower()
)
for index, file in enumerate(jpg_files, start=1):
new_name = (
f"product_{index:03d}"
f"{file.suffix}"
)
print(
f"{file.name} -> {new_name}"
)
هنا لم نستخدم rename(). النتيجة مجرد معاينة للأسماء الجديدة. إذا رأيت:
photo_1.jpg -> product_001.jpgphoto_2.jpg -> product_002.jpgphoto_3.jpg -> product_003.jpg
فقد راجعت منطق التسمية قبل تغيير الملفات.
إضافة Prefix إلى الاسم
new_name = (
"invoice_"
+ file.name
)
print(new_name)
مثلًا 001.pdf تصبح invoice_001.pdf.
إضافة Suffix قبل الامتداد
new_name = (
f"{file.stem}_final"
f"{file.suffix}"
)
بهذا يصبح report.pdf هو report_final.pdf، بدل وضع النص بعد الامتداد.
استبدال جزء من الاسم
لتحويل old_report_01.xlsx إلى new_report_01.xlsx:
new_stem = file.stem.replace(
"old_report",
"new_report"
)
new_name = (
new_stem
+ file.suffix
)
استخدام stem يجعل الاستبدال في اسم الملف دون العبث بالامتداد.
استبدال المسافات بشرطة سفلية
new_stem = (
file.stem
.strip()
.replace(" ", "_")
)
new_name = (
new_stem
+ file.suffix
)
مثلًا my photo 01.jpg تصبح my_photo_01.jpg.
منع تضارب أسماء الملفات
قبل التنفيذ افحص هل الاسم الجديد موجود بالفعل:
new_path = file.with_name(new_name)
if (
new_path.exists()
and new_path != file
):
raise FileExistsError(
f"Target exists: "
f"{new_path.name}"
)
file.rename(new_path)
هذا فحص محافظ يمنعك من متابعة العملية عندما يوجد ملف آخر بالاسم الجديد.
سكربت نهائي: معاينة أولًا ثم تنفيذ عند التأكد
السكربت التالي يجمع تحديد المجلد، اختيار الامتداد، ترتيب الملفات، الترقيم، الحفاظ على الامتداد، فحص تضارب الأسماء، ثم التنفيذ الاختياري.
from pathlib import Path
FOLDER = Path(
r"C:\Users\Name\Pictures"
)
EXTENSION = ".jpg"
PREFIX = "product_"
APPLY_CHANGES = False
if not FOLDER.is_dir():
raise FileNotFoundError(
f"Folder not found: {FOLDER}"
)
files = sorted(
(
file
for file in FOLDER.iterdir()
if (
file.is_file()
and file.suffix.lower()
== EXTENSION.lower()
)
),
key=lambda file: file.name.lower()
)
planned = []
for index, file in enumerate(
files,
start=1
):
new_name = (
f"{PREFIX}{index:03d}"
f"{file.suffix}"
)
new_path = file.with_name(new_name)
planned.append(
(file, new_path)
)
for old_path, new_path in planned:
if (
new_path.exists()
and new_path != old_path
):
raise FileExistsError(
f"Target already exists: "
f"{new_path.name}"
)
for old_path, new_path in planned:
print(
f"{old_path.name} "
f"-> {new_path.name}"
)
if APPLY_CHANGES:
for old_path, new_path in planned:
if old_path != new_path:
old_path.rename(new_path)
print("Rename completed.")
else:
print(
"Dry run only. "
"No files were renamed."
)
اترك APPLY_CHANGES = False في أول تشغيل. بعد مراجعة كل سطر من Old → New غيّرها إلى True ونفذ مرة أخرى.
ملاحظة عن ترتيب الأسماء
الترتيب السابق نصي. لذلك أسماء مثل photo_2.jpg وphoto_10.jpg قد لا تأتي بالترتيب العددي الذي يتوقعه الإنسان. إذا كان ترتيب الأرقام مهمًا، استخدم أسماء بأرقام ثابتة الطول مثل photo_002.jpg وphoto_010.jpg أو أضف Natural Sort مخصصة.
أخطاء شائعة
FileNotFoundError أو مسار خاطئ
تأكد أن FOLDER يشير إلى مجلد موجود. في Windows استخدم Raw String عند كتابة Backslashes يدويًا.
PermissionError
قد يكون الملف مفتوحًا في برنامج آخر أو لا تملك صلاحية تعديله. أغلق البرنامج وتحقق من الصلاحيات.
تشغيل السكربت على المجلد الخطأ
راجع قيمة FOLDER ونتيجة Dry Run قبل تغيير أي ملف.
الاسم الجديد موجود مسبقًا
افحص new_path.exists() وأوقف التنفيذ بدل المخاطرة بملف آخر.
إعادة تسمية السكربت نفسه
ضع السكربت خارج مجلد الملفات أو استهدف امتدادًا محددًا مثل JPG أو PDF.
تغيير الامتداد بالخطأ
استخدم stem لتعديل الاسم وsuffix للحفاظ على الامتداد.
روابط داخلية مفيدة من بايثون العرب
- تنظيم الملفات تلقائيًا حسب النوع والامتداد باستخدام pathlib وshutil — خطوة تالية مناسبة إذا كنت تريد أيضًا نقل الملفات إلى مجلدات منظمة.
- شرح مكتبة os للتعامل مع الملفات والمجلدات — لفهم أدوات نظام التشغيل والمسارات بشكل أوسع.
- مكتبة أوامر بايثون — مفيدة لمراجعة أمر تشغيل ملف بايثون من CMD أو Terminal.
مصادر رسمية للتوسع
الخلاصة
إذا كان لديك عشرات أو مئات الملفات، استخدم pathlib لعرضها وبناء الأسماء الجديدة، وsorted() لتثبيت قاعدة الترتيب، وf"{index:03d}" للترقيم، وsuffix للحفاظ على الامتداد.
الأهم هو الأمان: عاين الأسماء أولًا، افحص وجود الاسم الجديد، ثم نفّذ إعادة التسمية على نسخة تجريبية قبل ملفاتك الأصلية.
أفضل ممارسة: اجعل وضع المعاينة هو الوضع الافتراضي لأي سكربت يغيّر أسماء عدد كبير من الملفات.
أسئلة شائعة
كيف أعيد تسمية عدة ملفات باستخدام بايثون؟
اعرض الملفات داخل المجلد باستخدام Path.iterdir()، وابنِ الاسم الجديد داخل حلقة، ثم استخدم Path.rename() بعد معاينة النتيجة.
كيف أرقم الملفات تلقائيًا؟
استخدم enumerate() مع تنسيق مثل f"{index:03d}" للحصول على 001 و002 و003.
كيف أحافظ على امتداد الملفات؟
استخدم file.suffix عند بناء الاسم الجديد، وfile.stem للتعامل مع الاسم بدون الامتداد.
كيف أعيد تسمية ملفات JPG فقط؟
فلتر الملفات بشرط مثل file.suffix.lower() == ".jpg".
كيف أستبدل جزءًا من اسم الملف؟
استخدم file.stem.replace("old", "new") ثم أعد إضافة file.suffix.
كيف أتجنب الكتابة فوق ملف موجود؟
افحص new_path.exists() قبل rename()، وإذا كان الاسم موجودًا أوقف العملية أو اختر اسمًا آخر.


