جدول المحتويات

  • مشكلة معالجة مسار ملف بايثون
  • خلق المسارات
  • قراءة وكتابة الملفات
  • انتقاء مكونات المسار
  • نقل وحذف الملفات
  • أمثلة
    عد الملفات
    عرض شجرة الدليل
    ابحث عن آخر ملف تم تعديله
    قم بإنشاء اسم ملف فريد
  • اختلافات نظام التشغيل
  • المسارات ككائنات مناسبة
  • خاتمة

هل واجهت صعوبة في التعامل مع مسار الملف في بايثون؟ في Python 3.4 وما فوق ، انتهى الصراع الآن! لم تعد بحاجة إلى خدش رأسك فوق التعليمات البرمجية مثل:

>>> path.rsplit('\\', maxsplit=1)[0]

أو الاستياء من الإسهاب في:

>>> os.path.isfile(os.path.join(os.path.expanduser('~'), 'realpython.txt'))

في هذا البرنامج التعليمي ، سوف ترى كيفية التعامل مع مسارات الملفات – أسماء الأدلة والملفات – في Python. ستتعلم طرقًا جديدة لقراءة الملفات وكتابتها ، ومعالجة المسارات ونظام الملفات الأساسي ، بالإضافة إلى الاطلاع على بعض الأمثلة حول كيفية سرد الملفات وتكرارها. باستخدام وحدة pathlib ، يمكن إعادة كتابة المثالين أعلاه باستخدام رمز Pythonic أنيق وقابل للقراءة مثل:

>>> path.parent
>>> (pathlib.Path.home() / 'realpython.txt').is_file()

مشكلة معالجة مسار ملف بايثون

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

تقليديًا ، تمثل Python مسارات الملفات باستخدام سلاسل نصية عادية. بدعم من مكتبة os.path القياسية ، كان هذا مناسبًا على الرغم من كونه مرهقًا بعض الشيء (كما يوضح المثال الثاني في المقدمة). ومع ذلك ، نظرًا لأن المسارات ليست سلاسل ، تنتشر الوظائف المهمة في جميع أنحاء المكتبة القياسية ، بما في ذلك المكتبات مثل os و glob و shutil. يحتاج المثال التالي إلى ثلاث عبارات استيراد فقط لنقل جميع الملفات النصية إلى دليل أرشيف:

import glob
import os
import shutil

for file_name in glob.glob('*.txt'):
    new_path = os.path.join('archive', file_name)
    shutil.move(file_name, new_path)

مع المسارات التي يتم تمثيلها بواسطة سلاسل ، من الممكن ، ولكن عادة ما تكون فكرة سيئة ، استخدام طرق سلسلة منتظمة. على سبيل المثال ، بدلاً من ضم مسارين مع + مثل السلاسل العادية ، يجب عليك استخدام os.path.join () ، الذي يربط المسارات باستخدام فاصل المسار الصحيح في نظام التشغيل. تذكر أن Windows يستخدم \ بينما يستخدم Mac و Linux / كفاصل. يمكن أن يؤدي هذا الاختلاف إلى أخطاء يصعب تحديدها ، مثل مثالنا الأول في المقدمة الذي يعمل مع مسارات Windows فقط.

تم تقديم وحدة pathlib في Python 3.4 (PEP 428) للتعامل مع هذه التحديات. إنه يجمع الوظائف الضرورية في مكان واحد ويجعلها متاحة من خلال الأساليب والخصائص على كائن مسار سهل الاستخدام.

في وقت مبكر ، لا تزال الحزم الأخرى تستخدم سلاسل لمسارات الملفات ، ولكن اعتبارًا من Python 3.6 ، يتم دعم وحدة pathlib في جميع أنحاء المكتبة القياسية ، ويرجع ذلك جزئيًا إلى إضافة بروتوكول مسار نظام الملفات. إذا كنت عالقًا في Python القديمة ، فهناك أيضًا منفذ خلفي متاح لـ Python 2.

حان وقت العمل: دعونا نرى كيف يعمل pathlib عمليًا.

خلق المسارات

كل ما تحتاج إلى معرفته حقًا هو فئة pathlib.Path. هناك عدة طرق مختلفة لإنشاء المسار. أولاً وقبل كل شيء ، هناك طرق فصل مثل .cwd () (دليل العمل الحالي) و .home () (الدليل الرئيسي للمستخدم):

>>> import pathlib
>>> pathlib.Path.cwd()
PosixPath('/home/gahjelle/realpython/')

ملاحظة: خلال هذا البرنامج التعليمي ، سنفترض أن pathlib قد تم استيراده ، دون توضيح استيراد pathlib على النحو الوارد أعلاه. نظرًا لأنك ستستخدم فئة المسار بشكل أساسي ، يمكنك أيضًا القيام بذلك من pathlib import Path وكتابة Path بدلاً من pathlib.Path.

يمكن أيضًا إنشاء المسار بشكل صريح من تمثيل السلسلة الخاص به:

>>> pathlib.Path(r'C:\Users\gahjelle\realpython\file.txt')
WindowsPath('C:/Users/gahjelle/realpython/file.txt')

نصيحة صغيرة للتعامل مع مسارات Windows: في Windows ، يكون فاصل المسار عبارة عن شرطة مائلة للخلف ، \. ومع ذلك ، في العديد من السياقات ، تُستخدم الشرطة المائلة العكسية أيضًا كحرف هروب من أجل تمثيل الأحرف غير القابلة للطباعة. لتجنب المشاكل ، استخدم القيم الحرفية للسلسلة الأولية لتمثيل مسارات Windows. هذه عبارة عن سلسلة حرفية لها حرف r مُسبق لها. في سلسلة الأحرف الأولية ، يمثل \ خط مائل عكسي حرفي: r’C: \ Users ‘.

الطريقة الثالثة لبناء مسار هي الانضمام إلى أجزاء المسار باستخدام عامل التشغيل الخاص /. يتم استخدام عامل تشغيل الشرطة المائلة للأمام بشكل مستقل عن فاصل المسار الفعلي على المنصة:

>>> pathlib.Path.home() / 'python' / 'scripts' / 'test.py'
PosixPath('/home/gahjelle/python/scripts/test.py')

يمكن أن يصل / إلى عدة مسارات أو مزيج من المسارات والسلاسل (على النحو الوارد أعلاه) طالما أن هناك كائن مسار واحد على الأقل. إذا لم تعجبك الخاص / الترميز ، يمكنك فعل الشيء نفسه باستخدام طريقة .joinpath ():

>>> pathlib.Path.home().joinpath('python', 'scripts', 'test.py')
PosixPath('/home/gahjelle/python/scripts/test.py')

لاحظ أنه في الأمثلة السابقة ، يتم تمثيل pathlib.Path إما بواسطة WindowsPath أو PosixPath. يعتمد الكائن الفعلي الذي يمثل المسار على نظام التشغيل الأساسي. (بمعنى ، تم تشغيل مثال WindowsPath على نظام التشغيل Windows ، بينما تم تشغيل أمثلة PosixPath على نظام التشغيل Mac أو Linux.) راجع قسم “اختلافات نظام التشغيل” لمزيد من المعلومات.

قراءة وكتابة الملفات

تقليديًا ، كانت طريقة قراءة أو كتابة ملف في Python هي استخدام وظيفة open () المضمنة. لا يزال هذا صحيحًا لأن الوظيفة open () يمكنها استخدام كائنات المسار مباشرةً. يعثر المثال التالي على جميع الرؤوس في ملف Markdown ويطبعها:

path = pathlib.Path.cwd() / 'test.md'
with open(path, mode='r') as fid:
    headers = [line.strip() for line in fid if line.startswith('#')]
print('\n'.join(headers))

بديل مكافئ هو استدعاء .open () على كائن المسار:

with path.open(mode='r') as fid:
    ...

في الواقع ، يقوم Path.open () باستدعاء العنصر الداخلي open () خلف الكواليس. الخيار الذي تستخدمه هو في الأساس مسألة ذوق.

لقراءة الملفات وكتابتها بشكل بسيط ، هناك طريقتان ملائمتان في مكتبة pathlib:

  • .read_text (): افتح المسار في وضع النص وأعد المحتويات كسلسلة.
  • .read_bytes (): افتح المسار في الوضع الثنائي / البايت وأعد المحتويات كاختبار بايت.
  • .write_text (): افتح المسار واكتب بيانات السلسلة إليه.
  • .write_bytes (): افتح المسار في الوضع الثنائي / بايت واكتب البيانات إليه.

كل من هذه الطرق تتعامل مع فتح وإغلاق الملف ، مما يجعلها سهلة الاستخدام ، على سبيل المثال:

>>> path = pathlib.Path.cwd() / 'test.md'
>>> path.read_text()
<the contents of the test.md-file>

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

>>> pathlib.Path('test.md').read_text()
<the contents of the test.md-file>

سيجد الأسلوب .resolve () المسار الكامل. أدناه ، نؤكد أن دليل العمل الحالي يُستخدم لأسماء الملفات البسيطة:

>>> path = pathlib.Path('test.md')
>>> path.resolve()
PosixPath('/home/gahjelle/realpython/test.md')

>>> path.resolve().parent == pathlib.Path.cwd()
True

>>> path.parent == pathlib.Path.cwd()
False

لاحظ أنه عند مقارنة المسارات ، يتم مقارنة تمثيلاتها. في المثال أعلاه ، path.parent لا يساوي pathlib.Path.cwd () ، لأن path.parent يتم تمثيله بواسطة “.” بينما يتم تمثيل pathlib.Path.cwd () بـ “/ home / gahjelle / realpython /”.

انتقاء مكونات المسار

الأجزاء المختلفة من المسار متوفرة بسهولة كخصائص. تشمل الأمثلة الأساسية ما يلي:

  • .name: اسم الملف بدون أي دليل
  • .parent: الدليل الذي يحتوي على الملف ، أو الدليل الأصل إذا كان المسار عبارة عن دليل
  • .stem: اسم الملف بدون اللاحقة
  • .suffix: امتداد الملف
  • .anchor: جزء المسار قبل الدلائل

فيما يلي هذه الخصائص قيد التشغيل:

>>> path
PosixPath('/home/gahjelle/realpython/test.md')
>>> path.name
'test.md'
>>> path.stem
'test'
>>> path.suffix
'.md'
>>> path.parent
PosixPath('/home/gahjelle/realpython')
>>> path.parent.parent
PosixPath('/home/gahjelle')
>>> path.anchor
'/'

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

>>> path.parent.parent / ('new' + path.suffix)
PosixPath('/home/gahjelle/new.md')

توفر ورقة غش Pathlib الممتازة تمثيلًا مرئيًا لهذه الخصائص والطرق وغيرها.

نقل وحذف الملفات

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

لنقل ملف ، استخدم .replace (). لاحظ أنه إذا كانت الوجهة موجودة بالفعل ، فسيحل محلها .replace (). لسوء الحظ ، لا يدعم pathlib صراحة النقل الآمن للملفات. لتجنب احتمال الكتابة فوق مسار الوجهة ، فإن أبسط شيء هو اختبار ما إذا كانت الوجهة موجودة قبل استبدال:

if not destination.exists():
    source.replace(destination)

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

with destination.open(mode='xb') as fid:
    fid.write(source.read_bytes())

سيؤدي الكود أعلاه إلى رفع FileExistsError إذا كانت الوجهة موجودة بالفعل. من الناحية الفنية ، هذا ينسخ ملفًا. لإجراء نقل ، ما عليك سوى حذف المصدر بعد الانتهاء من النسخ (انظر أدناه). تأكد من عدم وجود استثناء على الرغم من.

عندما تعيد تسمية الملفات ، قد تكون الطرق المفيدة .with_name () و .with_suffix (). كلاهما يعيد المسار الأصلي ولكن مع استبدال الاسم أو اللاحقة ، على التوالي.

على سبيل المثال:

>>> path
PosixPath('/home/gahjelle/realpython/test001.txt')
>>> path.with_suffix('.py')
PosixPath('/home/gahjelle/realpython/test001.py')
>>> path.replace(path.with_suffix('.py'))

يمكن حذف الدلائل والملفات باستخدام .rmdir () و .unlink () على التوالي. (مرة أخرى ، كن حذرا!)

أمثلة

في هذا القسم ، سترى بعض الأمثلة على كيفية استخدام pathlib للتعامل مع التحديات البسيطة.

عد الملفات

هناك عدة طرق مختلفة لسرد العديد من الملفات. أبسطها هي طريقة .iterdir () ، والتي تتكرر عبر جميع الملفات في الدليل المحدد. يجمع المثال التالي بين .iterdir () والمجموعات. فئة Counter لحساب عدد الملفات الموجودة لكل نوع ملف في الدليل الحالي:

>>> import collections
>>> collections.Counter(p.suffix for p in pathlib.Path.cwd().iterdir())
Counter({'.md': 2, '.txt': 4, '.pdf': 2, '.py': 1})

يمكن إنشاء قوائم ملفات أكثر مرونة باستخدام الأساليب .glob () و .rglob () (الكرة العودية العودية). على سبيل المثال ، يقوم pathlib.Path.cwd (). glob (‘*. txt’) بإرجاع جميع الملفات التي تحتوي على لاحقة .txt في الدليل الحالي. فيما يلي فقط أنواع الملفات التي تبدأ بـ p:

>>> import collections
>>> collections.Counter(p.suffix for p in pathlib.Path.cwd().glob('*.p*'))
Counter({'.pdf': 2, '.py': 1})

عرض شجرة الدليل

يحدد المثال التالي دالة ، الشجرة () ، والتي ستطبع شجرة مرئية تمثل التسلسل الهرمي للملف ، متجذرة في دليل معين. هنا ، نريد سرد الأدلة الفرعية أيضًا ، لذلك نستخدم طريقة .rglob ():

def tree(directory):
    print(f'+ {directory}')
    for path in sorted(directory.rglob('*')):
        depth = len(path.relative_to(directory).parts)
        spacer = '    ' * depth
        print(f'{spacer}+ {path.name}')

لاحظ أننا نحتاج إلى معرفة المسافة البُعدية التي يقع فيها الملف عن الدليل الجذر. للقيام بذلك ، نستخدم أولاً .relative_to () لتمثيل مسار متعلق بالدليل الجذر. بعد ذلك ، نحسب عدد الأدلة (باستخدام خاصية .parts) في التمثيل. عند التشغيل ، تنشئ هذه الوظيفة شجرة مرئية مثل ما يلي:

>>> tree(pathlib.Path.cwd())
+ /home/gahjelle/realpython
    + directory_1
        + file_a.md
    + directory_2
        + file_a.md
        + file_b.pdf
        + file_c.py
    + file_1.txt
    + file_2.txt

ملاحظة: لا تعمل سلاسل f إلا في Python 3.6 والإصدارات الأحدث. في لغة Pythons الأقدم ، يمكن كتابة التعبير f ‘{spacer} + {path.name}’ {0} + {1} ‘. (spacer، path.name).

ابحث عن آخر ملف تم تعديله

تعتبر طرق .iterdir () و .glob () و .rglob () مناسبة جدًا لتعبيرات المولد وفهم القوائم. للعثور على الملف في دليل تم تعديله مؤخرًا ، يمكنك استخدام طريقة .stat () للحصول على معلومات حول الملفات الأساسية. على سبيل المثال ، يعطي .stat (). st_mtime وقت آخر تعديل لملف:

>>> from datetime import datetime
>>> time, file_path = max((f.stat().st_mtime, f) for f in directory.iterdir())
>>> print(datetime.fromtimestamp(time), file_path)
2018-03-23 19:23:56.977817 /home/gahjelle/realpython/test001.txt

يمكنك حتى الحصول على محتويات الملف الذي تم تعديله آخر مرة بتعبير مشابه:

>>> max((f.stat().st_mtime, f) for f in directory.iterdir())[1].read_text()
<the contents of the last modified file in directory>

يمثل الطابع الزمني الذي تم إرجاعه من خصائص .stat (). st_ المختلفة الثواني منذ الأول من يناير 1970. بالإضافة إلى datetime.fromtimestamp ، يمكن استخدام time.localtime أو time.ctime لتحويل الطابع الزمني إلى شيء أكثر قابلية للاستخدام.

قم بإنشاء اسم ملف فريد

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

def unique_path(directory, name_pattern):
    counter = 0
    while True:
        counter += 1
        path = directory / name_pattern.format(counter)
        if not path.exists():
            return path

path = unique_path(pathlib.Path.cwd(), 'test{:03d}.txt')

إذا كان الدليل يحتوي بالفعل على الملفين test001.txt و test002.txt ، فسيقوم الرمز أعلاه بتعيين المسار إلى test003.txt.

اختلافات نظام التشغيل

لاحظنا سابقًا أنه عندما قمنا بإنشاء مثيل لـ pathlib.Path ، تم إرجاع كائن WindowsPath أو PosixPath. يعتمد نوع الكائن على نظام التشغيل الذي تستخدمه. هذه الميزة تجعل من السهل إلى حد ما كتابة رمز متوافق عبر الأنظمة الأساسية. من الممكن أن تطلب WindowsPath أو PosixPath صراحة ، لكنك ستقتصر رمزك على هذا النظام فقط دون أي فوائد. لا يمكن استخدام مسار ملموس مثل هذا في نظام مختلف:

>>> pathlib.WindowsPath('test.md')
NotImplementedError: cannot instantiate 'WindowsPath' on your system

قد تكون هناك أوقات تحتاج فيها إلى تمثيل المسار دون الوصول إلى نظام الملفات الأساسي (في هذه الحالة قد يكون من المنطقي أيضًا تمثيل مسار Windows على نظام بخلاف Windows أو العكس). يمكن القيام بذلك باستخدام كائنات PurePath. تدعم هذه الكائنات العمليات التي تمت مناقشتها في القسم الخاص بمكونات المسار ولكن ليس الطرق التي تصل إلى نظام الملفات:

>>> path = pathlib.PureWindowsPath(r'C:\Users\gahjelle\realpython\file.txt')
>>> path.name
'file.txt'
>>> path.parent
PureWindowsPath('C:/Users/gahjelle/realpython')
>>> path.exists()
AttributeError: 'PureWindowsPath' object has no attribute 'exists'

يمكنك إنشاء مثيل PureWindowsPath أو PurePosixPath مباشرة على جميع الأنظمة. سيؤدي Instantiating PurePath إلى إرجاع أحد هذه الكائنات اعتمادًا على نظام التشغيل الذي تستخدمه.

المسارات ككائنات مناسبة

في المقدمة ، لاحظنا بإيجاز أن المسارات ليست سلاسل ، والدافع وراء pathlib هو تمثيل نظام الملفات بالكائنات المناسبة. في الواقع ، التوثيق الرسمي لـ pathlib هو pathlib – مسارات نظام الملفات الموجهة للكائنات. إن النهج الموجه للكائنات مرئي بالفعل في الأمثلة أعلاه (خاصة إذا كنت تتناقض مع طريقة os.path القديمة للقيام بالأشياء). ومع ذلك ، دعني أترك لك بعض الحكايات الأخرى.

بصرف النظر عن نظام التشغيل الذي تستخدمه ، يتم تمثيل المسارات بأسلوب Posix ، مع استخدام الشرطة المائلة للأمام كفاصل للمسار. في Windows ، سترى شيئًا كهذا:

>>> pathlib.Path(r'C:\Users\gahjelle\realpython\file.txt')
WindowsPath('C:/Users/gahjelle/realpython/file.txt')

ومع ذلك ، عندما يتم تحويل مسار إلى سلسلة ، فإنه سيستخدم النموذج الأصلي ، على سبيل المثال مع خطوط مائلة عكسية على Windows:

>>> str(pathlib.Path(r'C:\Users\gahjelle\realpython\file.txt'))
'C:\\Users\\gahjelle\\realpython\\file.txt'

هذا مفيد بشكل خاص إذا كنت تستخدم مكتبة لا تعرف كيفية التعامل مع كائنات pathlib.Path. هذه مشكلة أكبر في إصدارات Python قبل 3.6. على سبيل المثال ، في Python 3.5 ، يمكن لمكتبة configparser القياسية استخدام مسارات سلسلة فقط لقراءة الملفات. طريقة معالجة مثل هذه الحالات هي القيام بالتحويل إلى سلسلة بشكل صريح:

>>> from configparser import ConfigParser
>>> path = pathlib.Path('config.txt')
>>> cfg = ConfigParser()
>>> cfg.read(path)                     # Error on Python < 3.6
TypeError: 'PosixPath' object is not iterable
>>> cfg.read(str(path))                # Works on Python >= 3.4
['config.txt']

في Python 3.6 والإصدارات الأحدث ، يوصى باستخدام os.fspath () بدلاً من str () إذا كنت بحاجة إلى إجراء تحويل صريح. يعد هذا أكثر أمانًا لأنه سيؤدي إلى حدوث خطأ إذا حاولت عن طريق الخطأ تحويل كائن لا يشبه المسار.

من المحتمل أن يكون الجزء الأكثر غرابة من مكتبة pathlib هو استخدام العامل /. لإلقاء نظرة خاطفة على الغطاء ، دعونا نرى كيف يتم تنفيذ ذلك. هذا مثال على التحميل الزائد للمشغل: يتغير سلوك المشغل حسب السياق. لقد رأيت هذا من قبل. فكر في كيف + تعني أشياء مختلفة للسلاسل والأرقام. تنفذ Python التحميل الزائد للمشغل من خلال استخدام أساليب الشرطة السفلية المزدوجة (المعروفة أيضًا بأساليب dunder).

يتم تحديد عامل التشغيل / بواسطة طريقة .__ truediv __ (). في الواقع ، إذا ألقيت نظرة على الكود المصدري لـ pathlib ، فسترى شيئًا مثل:

class PurePath(object):

    def __truediv__(self, key):
        return self._make_child((key,))

خاتمة

منذ Python 3.4 ، أصبح pathlib متاحًا في المكتبة القياسية. باستخدام pathlib ، يمكن تمثيل مسارات الملفات بواسطة كائنات المسار المناسبة بدلاً من السلاسل العادية كما في السابق. هذه الكائنات تجعل التعليمات البرمجية تتعامل مع مسارات الملفات:

  • أسهل للقراءة ، خاصةً لأنه / يُستخدم لربط المسارات معًا
  • أكثر قوة ، مع توفر معظم الأساليب والخصائص الضرورية مباشرة على الكائن
  • أكثر اتساقًا عبر أنظمة التشغيل ، حيث يتم إخفاء خصائص الأنظمة المختلفة بواسطة كائن المسار

في هذا البرنامج التعليمي ، رأيت كيفية إنشاء كائنات المسار ، وقراءة الملفات وكتابتها ، ومعالجة المسارات ونظام الملفات الأساسي ، بالإضافة إلى بعض الأمثلة عن كيفية التكرار عبر العديد من مسارات الملفات.