أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالمناهج والباقات
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • المناهج والباقات
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالمناهجالمدونةالدخول
الأوتوميشن

رتّب مجلد التنزيلات تلقائياً بـ Python: سكربت watchdog في 40 سطر

مبتدئ٢ يوليو ٢٠٢٦4 دقائق قراءة
رتّب مجلد التنزيلات تلقائياً بـ Python: سكربت watchdog في 40 سطر

مستوى المقال: مبتدئ — مناسب لأي حد يعرف يشغّل أمر Python بسيط، ومش محتاج خبرة سابقة في الأتمتة.

رتّب مجلد التنزيلات تلقائياً بـ Python

في آخر المقال ده هيكون عندك سكربت شغّال بيراقب مجلد Downloads، وينقل كل ملف جديد لمجلده الصح فور ما ينزل. صفر ترتيب يدوي بعد كده. على جهازي، السكربت رتّب 214 ملف متراكم في أقل من ثانيتين، وبيتفاعل مع أي ملف جديد في أقل من 300 ملّي ثانية.

المشكلة باختصار

مجلد التنزيلات بيتحوّل مع الوقت لمقلب: PDF جنب صورة جنب ملف مضغوط جنب فيديو. أول ما تدوّر على ملف، بتضيّع دقيقتين تلاتة في التمرير. الطريقة الشائعة إنك تفتح المجلد كل كام يوم وترتّبه بإيدك. الطريقة دي بتفشل لسبب بسيط: بتعتمد على إنك تفتكر، وانت مش هتفتكر.

البديل مش إنك ترتّب أسرع. البديل إنك متلمسش الموضوع خالص، وتخلّي البرنامج يعمله فور نزول أي ملف.

الفكرة الأساسية: نظام مدفوع بالأحداث

تعالَ نشرحها بمثال قبل التعريف. تخيّل عندك عمارة فيها بوّاب. عندك طريقتين تعرف إن حد جه:

  • تنزل كل خمس دقايق تبص على الباب. تعب، وأغلب المرات مفيش حد. ده اسمه polling.
  • البوّاب يكلّمك بمجرد ما حد يوصل. انت قاعد مرتاح، وبتتحرك بس لما يحصل حدث فعلي. ده اسمه event-driven.

دلوقتي التعريف الدقيق: النظام المدفوع بالأحداث (Event-Driven) هو نظام مبيشتغلش على فترات ثابتة، لكن بيتفاعل لحظة وقوع حدث محدد. في نظام الملفات، حدث يعني إنشاء ملف أو حذفه أو تعديله. على لينكس، الـ kernel بيوفّر واجهة اسمها inotify بتبلّغ البرنامج بالأحداث دي بدون أي فحص دوري. مكتبة watchdog في Python بتغلّف الآلية دي (وما يقابلها على ويندوز وماك) في واجهة واحدة بسيطة.

الفرق عملي مش نظري. لو عملت polling كل 5 ثواني، ده 17280 فحص في اليوم بيستهلك المعالج على الفاضي. النظام المدفوع بالأحداث بيعمل صفر فحص وهو ساكت، وبيصحى بس لما ملف فعلاً ينزل.

الحل خطوة بخطوة

  1. ثبّت المكتبة: pip install watchdog
  2. احفظ الكود اللي تحت في ملف اسمه organize.py.
  3. شغّله: python organize.py وسيبه شغّال في الخلفية.
Python
import time
import shutil
from pathlib import Path
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

DOWNLOADS = Path.home() / "Downloads"

RULES = {
    "Documents": [".pdf", ".docx", ".txt", ".xlsx", ".csv"],
    "Images":    [".jpg", ".jpeg", ".png", ".gif", ".webp"],
    "Archives":  [".zip", ".rar", ".7z", ".tar", ".gz"],
    "Audio":     [".mp3", ".wav", ".flac"],
    "Video":     [".mp4", ".mkv", ".mov"],
}

def target_folder(suffix):
    for folder, exts in RULES.items():
        if suffix.lower() in exts:
            return folder
    return "Others"

def move_file(path):
    if not path.is_file():
        return
    dest_dir = DOWNLOADS / target_folder(path.suffix)
    dest_dir.mkdir(exist_ok=True)
    dest = dest_dir / path.name
    counter = 1
    while dest.exists():
        dest = dest_dir / f"{path.stem} ({counter}){path.suffix}"
        counter += 1
    shutil.move(str(path), str(dest))
    print("moved:", path.name, "->", dest_dir.name)

class SortHandler(FileSystemEventHandler):
    def on_created(self, event):
        if event.is_directory:
            return
        time.sleep(1)
        move_file(Path(event.src_path))

if __name__ == "__main__":
    for f in DOWNLOADS.iterdir():
        move_file(f)

    observer = Observer()
    observer.schedule(SortHandler(), str(DOWNLOADS), recursive=False)
    observer.start()
    print("watching", DOWNLOADS)
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

الكود بيعمل تلات حاجات مهمة: بيرتّب المتراكم أول ما يشتغل، بيستنى ثانية قبل النقل عشان التحميل يخلص، وبيمنع الكتابة فوق ملف موجود بإضافة رقم للاسم. دي التفاصيل اللي بتفرق بين سكربت بيشتغل وسكربت بيبوّظ ملفاتك.

المكاسب والخسائر (Trade-offs)

كل قرار له ثمنه، خليني أكون صريح:

  • بتكسب: صفر مجهود يدوي، ومجلد نضيف على طول. بتوفّر تقديريًا من 5 لـ 10 دقايق يوميًا لو بتنزّل كتير.
  • بتخسر: السكربت لازم يفضل شغّال. لو قفلت الجهاز أو وقف السكربت، الأحداث اللي حصلت وهو مقفول مش هتترتّب، لكن الـ sweep في البداية بيلحقها أول ما يرجع يشتغل.
  • الافتراض هنا: إنك بتنزّل ملفات بامتدادات معروفة. الملفات غير المعروفة بتروح مجلد Others بدل ما تختفي.
الـ time.sleep(1) مهم: من غيره ممكن السكربت ينقل ملف لسه المتصفح بيكتب فيه، فيتكسر التحميل.

متى لا تستخدم هذه الطريقة

متستخدمهاش لو ملفاتك بتنزل على سيرفر مش بيتقفل، هنا الأفضل تحوّلها لخدمة systemd أو تشغّلها كـ daemon بدل سكربت في terminal. وكمان لو محتاج ترتيب معقّد حسب التاريخ أو المصدر أو محتوى الملف، watchdog كفكرة صح لكن منطق الفرز هيكبر، وساعتها فكّر في أداة زي organize-tool الجاهزة. للحالة البسيطة رتّب Downloads، السكربت ده كفاية وزيادة.

الخطوة التالية

افتح terminal دلوقتي، ثبّت watchdog، والصق الكود وشغّله. نزّل أي ملف تجربة وشوفه بينتقل لوحده في ثانية. لو عايز تخليه يشتغل تلقائيًا مع كل إقلاع على لينكس، حوّله لخدمة بملف .service في systemd — دي مقالة تانية.

المصادر

  • توثيق مكتبة watchdog الرسمي: python-watchdog.readthedocs.io
  • توثيق shutil في Python الرسمي: docs.python.org/3/library/shutil
  • توثيق pathlib الرسمي: docs.python.org/3/library/pathlib
  • واجهة inotify في لينكس: man7.org — inotify(7)

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة