python - كيف أقوم بإدراج جميع ملفات الدليل؟




directory (25)

قائمة جميع الملفات في الدليل:

import os
from os import path

files = [x for x in os.listdir(directory_path) if path.isfile(directory_path+os.sep+x)]

هنا ، يمكنك الحصول على قائمة بكل الملفات في الدليل.

كيف يمكنني إدراج جميع ملفات الدليل في Python وإضافتها إلى list ؟


import os
def get_files(search_path):
     for (dirpath, _, filenames) in os.walk(search_path):
         for filename in filenames:
             yield os.path.join(dirpath, filename)
list_files = get_files('.')
for filename in list_files:
    print(filename)

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

[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]

تعديل ملحقات الملفات ومسار المصدر حسب الحاجة.


إذا كنت تهتم بالأداء ، حاول scandir. بالنسبة إلى Python 2.x ، قد تحتاج إلى تثبيته يدويًا. أمثلة:

def scan_path(path):
    de = scandir.scandir(path)
    while 1:
        try:
            e = de.next()
            if e.is_dir():
                scan_path(e.path)
            else:
                print e.path
        except StopIteration as _:
                break

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

import os

def createList(foldername, fulldir = True, suffix=".jpg"):
    file_list_tmp = os.listdir(foldername)
    #print len(file_list_tmp)
    file_list = []
    if fulldir:
        for item in file_list_tmp:
            if item.endswith(suffix):
                file_list.append(os.path.join(foldername, item))
    else:
        for item in file_list_tmp:
            if item.endswith(suffix):
                file_list.append(item)
    return file_list

وهنا وظيفة للأغراض العامة لهذا الغرض. تقوم بإرجاع قائمة مسارات الملفات بدلاً من أسماء الملفات لأنني وجدت أن ذلك أكثر فائدة. لديها عدد قليل من الحجج الاختيارية التي تجعلها متعددة الجوانب. على سبيل المثال ، غالبًا ما أستخدمها مع حجج مثل pattern='*.txt'أو subfolders=True.

(py35x64_test) E:\Work\Dev\\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os;os.system(\"dir /b root_dir\")"
dir0
dir1
dir2
dir3
file0
file1

def list_files(path):
    # returns a list of names (with extension, without full path) of all files 
    # in folder path
    files = []
    for name in os.listdir(path):
        if os.path.isfile(os.path.join(path, name)):
            files.append(name)
    return files 

قدم Python 3.5 طريقة جديدة وأسرع للمشي خلال الدليل - os.scandir().

مثال:

for file in os.scandir('/usr/bin'):
    line = ''
    if file.is_file():
        line += 'f'
    elif file.is_dir():
        line += 'd'
    elif file.is_symlink():
        line += 'l'
    line += '\t'
    print("{}{}".format(line, file.name))

سوف تحصل على os.listdir() كل ما يوجد في دليل - الملفات والدلائل.

إذا كنت تريد فقط الملفات ، يمكنك إما تصفية هذا لأسفل باستخدام os.path :

from os import listdir
from os.path import isfile, join
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]

أو يمكنك استخدام os.walk() الذي سيعطي قائمتين لكل دليل os.walk() - تقسيم إلى ملفات و dirs لك. إذا كنت تريد فقط أعلى دليل يمكنك فقط كسر أول مرة تنتج

from os import walk

f = []
for (dirpath, dirnames, filenames) in walk(mypath):
    f.extend(filenames)
    break

وأخيرًا ، كما يظهر هذا المثال ، فإن إضافة قائمة إلى أخرى يمكنك إما استخدام .extend() أو

>>> q = [1, 2, 3]
>>> w = [4, 5, 6]
>>> q = q + w
>>> q
[1, 2, 3, 4, 5, 6]

أنا شخصياً أفضل .extend()


حل من سطر واحد للحصول على قائمة بالملفات فقط (لا توجد أدلة فرعية):

filenames = next(os.walk(path))[2]

أو أسماء المسار المطلقة:

paths = [os.path.join(path,fn) for fn in next(os.walk(path))[2]]

إذا كنت تبحث عن تطبيق بايثون للبحث ، فهذه وصفة أستخدمها كثيرًا بشكل متكرر:

from findtools.find_files import (find_files, Match)

# Recursively find all *.sh files in **/usr/bin**
sh_files_pattern = Match(filetype='f', name='*.sh')
found_files = find_files(path='/usr/bin', match=sh_files_pattern)

for found_file in found_files:
    print found_file

لذا قمت بإعداد package PyPI منه وهناك أيضًا مستودع GitHub . أتمنى أن يجد شخص ما مفيدًا لهذا الرمز.


الجزء الأول 1

ملاحظات أولية

  • على الرغم من وجود اختلاف واضح بين مصطلحات الملف والدليل في نص السؤال ، قد يجادل البعض بأن الأدلة هي في الواقع ملفات خاصة
  • العبارة: " جميع ملفات الدليل " يمكن تفسيرها بطريقتين:
    1. جميع المتحدرين مباشرة (أو المستوى 1) فقط
    2. جميع الأحفاد في شجرة الدليل بالكامل (بما في ذلك تلك الموجودة في الأدلة الفرعية)
  • عندما تم طرح السؤال ، أتخيل أن Python 2 ، كان إصدار LTS ، ولكن سيتم تشغيل نماذج التعليمة البرمجية بواسطة Python 3 ( .5 ) (سأحتفظ بها باعتبارها Python 2 متوافقة قدر الإمكان ؛ أيضًا ، أي رمز ينتمي إلى بايثون التي سأقوم بنشرها ، هي من الإصدار 3.5.5 - ما لم ينص على خلاف ذلك). لها عواقب مرتبطة بكلمة رئيسية أخرى في السؤال: " إضافتها إلى قائمة ":

    • في إصدارات Python 2.2 السابقة ، تم تمثيل معظم المتتاليات (المتكرّرة) بقوائم (tuples ، مجموعات ، ...)
    • في بيثون 2.2 ، تم تقديم مفهوم المولد ( [بايثون]: المولدات ) - بإذن من [بايثون]: بيان العائد ). مع مرور الوقت ، بدأت النظائر المولد تظهر للوظائف التي عاد / عمل مع القوائم
    • في بايثون 3 ، المولد هو السلوك الافتراضي
    • الآن ، لا أعرف ما إذا كانت إعادة قائمة ما زالت إلزامية (أو قيام المولد بعملها أيضًا) ، ولكن تمرير مولد إلى مُنشئ list ، سيؤدي إلى إنشاء قائمة للخروج منه (واستهلاكه أيضًا). يوضح المثال أدناه الاختلافات في [Python]: map ( function، iterable، ... )
    Python 2.7.10 (default, Mar  8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> m = map(lambda x: x, [1, 2, 3])  # Just a dummy lambda function
    >>> m, type(m)
    ([1, 2, 3], <type 'list'>)
    >>> len(m)
    3
    


    Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> m = map(lambda x: x, [1, 2, 3])
    >>> m, type(m)
    (<map object at 0x000001B4257342B0>, <class 'map'>)
    >>> len(m)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: object of type 'map' has no len()
    >>> lm0 = list(m)  # Construct a list out of the generator
    >>> lm0, type(lm0)
    ([1, 2, 3], <class 'list'>)
    >>>
    >>> lm1 = list(m)  # Construct a list out of the same generator
    >>> lm1, type(lm1)  # Empty list this time - generator already consumed
    ([], <class 'list'>)
    
  • سوف تستند الأمثلة إلى دليل يسمى root_dir بالهيكل التالي (هذا المثال لـ Win ، لكنني قمت بتكرار شجرة المجلد لـ Ux ( Lnx ) أيضًا):

    E:\Work\Dev\\q003207219>tree /f "root_dir"
    Folder PATH listing for volume Work
    Volume serial number is 00000029 3655:6FED
    E:\WORK\DEV\\Q003207219\ROOT_DIR
    │   file0
    │   file1
    │
    ├───dir0
    │   ├───dir00
    │   │   │   file000
    │   │   │
    │   │   └───dir000
    │   │           file0000
    │   │
    │   ├───dir01
    │   │       file010
    │   │       file011
    │   │
    │   └───dir02
    │       └───dir020
    │           └───dir0200
    ├───dir1
    │       file10
    │       file11
    │       file12
    │
    ├───dir2
    │   │   file20
    │   │
    │   └───dir20
    │           file200
    │
    └───dir3
    


محاليل

النهج البرنامجية:

  1. [بيثون]: السراج. listdir ( المسار = '.' )

    قم بإرجاع قائمة تحتوي على أسماء الإدخالات في الدليل المعطى بواسطة المسار. القائمة في ترتيب تعسفي ، ولا تتضمن الإدخالات الخاصة '.' و '..' ...


    >>> import os
    >>> root_dir = "root_dir"  # Path relative to current dir (os.getcwd())
    >>>
    >>> os.listdir(root_dir)  # List all the items in root_dir
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [item for item in os.listdir(root_dir) if os.path.isfile(os.path.join(root_dir, item))]  # Filter the items and only keep files (strip out directories)
    ['file0', 'file1']
    

    إليك مثال أكثر تفصيلاً ( code_os_listdir.py ):

    import os
    from pprint import pformat
    
    
    def _get_dir_content(path, include_folders, recursive):
        entries = os.listdir(path)
        for entry in entries:
            entry_with_path = os.path.join(path, entry)
            if os.path.isdir(entry_with_path):
                if include_folders:
                    yield entry_with_path
                if recursive:
                    for sub_entry in _get_dir_content(entry_with_path, include_folders, recursive):
                        yield sub_entry
            else:
                yield entry_with_path
    
    
    def get_dir_content(path, include_folders=True, recursive=True, prepend_folder_name=True):
        path_len = len(path) + len(os.path.sep)
        for item in _get_dir_content(path, include_folders, recursive):
            yield item if prepend_folder_name else item[path_len:]
    
    
    def _get_dir_content_old(path, include_folders, recursive):
        entries = os.listdir(path)
        ret = list()
        for entry in entries:
            entry_with_path = os.path.join(path, entry)
            if os.path.isdir(entry_with_path):
                if include_folders:
                    ret.append(entry_with_path)
                if recursive:
                    ret.extend(_get_dir_content_old(entry_with_path, include_folders, recursive))
            else:
                ret.append(entry_with_path)
        return ret
    
    
    def get_dir_content_old(path, include_folders=True, recursive=True, prepend_folder_name=True):
        path_len = len(path) + len(os.path.sep)
        return [item if prepend_folder_name else item[path_len:] for item in _get_dir_content_old(path, include_folders, recursive)]
    
    
    def main():
        root_dir = "root_dir"
        ret0 = get_dir_content(root_dir, include_folders=True, recursive=True, prepend_folder_name=True)
        lret0 = list(ret0)
        print(ret0, len(lret0), pformat(lret0))
        ret1 = get_dir_content_old(root_dir, include_folders=False, recursive=True, prepend_folder_name=False)
        print(len(ret1), pformat(ret1))
    
    
    if __name__ == "__main__":
        main()
    

    ملاحظات :

    • هناك تطبيقان:
      • واحد يستخدم المولدات (بالطبع في هذا المثال يبدو عديم الفائدة ، منذ أن قمت بتحويل النتيجة إلى قائمة على الفور)
      • الكلاسيكية (أسماء الوظائف التي تنتهي في _old )
    • يتم استخدام Recursion (للوصول إلى الدلائل الفرعية)
    • لكل تطبيق هناك وظيفتان:
      • واحد يبدأ بتسطير أسفل السطر ( _ ): "خاص" (لا يجب أن يسمى مباشرة) - يقوم بكل العمل
      • الرمز العام (غلاف أكثر من السابق): يقوم فقط بخلع المسار الأولي (إذا لزم الأمر) من الإدخالات التي تم إرجاعها. إنه تطبيق قبيح ، لكنها الفكرة الوحيدة التي يمكن أن أتي بها في هذه المرحلة
    • من حيث الأداء ، تكون المولدات أسرع بشكل عام (مع الأخذ في الاعتبار أوقات الإنشاء والتكرار ) ، لكنني لم أختبرها في وظائف متكررة ، كما أنني أقوم بالتكرار داخل الوظيفة عبر مولدات داخلية - لا أعرف كيف الأداء الودية هي
    • العب مع الحجج للحصول على نتائج مختلفة


    الإخراج :

    (py35x64_test) E:\Work\Dev\\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" "code_os_listdir.py"
    <generator object get_dir_content at 0x000001BDDBB3DF10> 22 ['root_dir\\dir0',
     'root_dir\\dir0\\dir00',
     'root_dir\\dir0\\dir00\\dir000',
     'root_dir\\dir0\\dir00\\dir000\\file0000',
     'root_dir\\dir0\\dir00\\file000',
     'root_dir\\dir0\\dir01',
     'root_dir\\dir0\\dir01\\file010',
     'root_dir\\dir0\\dir01\\file011',
     'root_dir\\dir0\\dir02',
     'root_dir\\dir0\\dir02\\dir020',
     'root_dir\\dir0\\dir02\\dir020\\dir0200',
     'root_dir\\dir1',
     'root_dir\\dir1\\file10',
     'root_dir\\dir1\\file11',
     'root_dir\\dir1\\file12',
     'root_dir\\dir2',
     'root_dir\\dir2\\dir20',
     'root_dir\\dir2\\dir20\\file200',
     'root_dir\\dir2\\file20',
     'root_dir\\dir3',
     'root_dir\\file0',
     'root_dir\\file1']
    11 ['dir0\\dir00\\dir000\\file0000',
     'dir0\\dir00\\file000',
     'dir0\\dir01\\file010',
     'dir0\\dir01\\file011',
     'dir1\\file10',
     'dir1\\file11',
     'dir1\\file12',
     'dir2\\dir20\\file200',
     'dir2\\file20',
     'file0',
     'file1']
    


  1. [بيثون]: السراج. scandir ( path = '.' ) ( !!! Python 3.5 + !!! على الرغم من أنني أعتقد أنه بالنسبة للإصدارات السابقة كانت وحدة منفصلة (تم نقلها أيضًا إلى Python 2 ))

    إرجاع مكرر من كائنات os.DirEntry المقابلة الإدخالات في الدليل المعطى بواسطة المسار . يتم الحصول على الإدخالات بترتيب تعسفي ، وإدخالات خاصة '.' و '..' غير مضمنة.

    يمكن أن يؤدي استخدام scandir () بدلاً من listdir () إلى زيادة أداء التعليمة البرمجية التي تحتاج أيضًا إلى نوع الملف أو معلومات سمة الملف ، لأن كائنات os.DirEntry تعرض هذه المعلومات إذا كان نظام التشغيل يوفرها عند مسح دليل. قد تقوم جميع طرق os.DirEntry بإجراء استدعاء نظام ، لكن is_dir() و is_file() عادة ما تتطلب فقط استدعاء نظام للروابط الرمزية ؛ os.DirEntry.stat() دائمًا استدعاء نظام على نظام Unix ، ولكنه يتطلب واحدًا فقط للروابط الرمزية على Windows.


    >>> import os
    >>> root_dir = os.path.join(".", "root_dir")  # Explicitly prepending current directory
    >>> root_dir
    '.\\root_dir'
    >>>
    >>> scandir_iterator = os.scandir(root_dir)
    >>> scandir_iterator
    <nt.ScandirIterator object at 0x00000268CF4BC140>
    >>> [item.path for item in scandir_iterator]
    ['.\\root_dir\\dir0', '.\\root_dir\\dir1', '.\\root_dir\\dir2', '.\\root_dir\\dir3', '.\\root_dir\\file0', '.\\root_dir\\file1']
    >>>
    >>> [item.path for item in scandir_iterator]  # Will yield an empty list as it was consumed by previous iteration (automatically performed by the list comprehension)
    []
    >>>
    >>> scandir_iterator = os.scandir(root_dir)  # Reinitialize the generator
    >>> for item in scandir_iterator :
    ...     if os.path.isfile(item.path):
    ...             print(item.name)
    ...
    file0
    file1
    

    ملاحظات :

    • انها مشابهة ل os.listdir
    • ولكنها أيضًا أكثر مرونة (وتوفر المزيد من الوظائف) ، والمزيد من بيثون (وفي بعض الحالات ، أسرع)


  1. [بيثون]: السراج. walk ( top، topdown = True، onerror = None، followlinks = False )

    قم بتوليد أسماء الملفات في شجرة دليل عن طريق المشي في الشجرة إما من أعلى لأسفل أو من أسفل إلى أعلى. لكل دليل في الشجرة المتجذرة في أعلى الدليل (بما في ذلك الجزء العلوي نفسه) ، ينتج عنه 3-tuple ( dirpath، dirnames، filenames).


    >>> import os
    >>> root_dir = os.path.join(os.getcwd(), "root_dir")  # Specify the full path
    >>> root_dir
    'E:\\Work\\Dev\\\\q003207219\\root_dir'
    >>>
    >>> walk_generator = os.walk(root_dir)
    >>> root_dir_entry = next(walk_generator)  # First entry corresponds to the root dir (that was passed as an argument)
    >>> root_dir_entry
    ('E:\\Work\\Dev\\\\q003207219\\root_dir', ['dir0', 'dir1', 'dir2', 'dir3'], ['file0', 'file1'])
    >>>
    >>> root_dir_entry[1] + root_dir_entry[2]  # Display the dirs and the files (that are direct descendants) in a single list
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [os.path.join(root_dir_entry[0], item) for item in root_dir_entry[1] + root_dir_entry[2]]  # Display all the entries in the previous list by their full path
    ['E:\\Work\\Dev\\\\q003207219\\root_dir\\dir0', 'E:\\Work\\Dev\\\\q003207219\\root_dir\\dir1', 'E:\\Work\\Dev\\\\q003207219\\root_dir\\dir2', 'E:\\Work\\Dev\\\\q003207219\\root_dir\\dir3', 'E:\\Work\\Dev\\\\q003207219\\root_dir\\file0', 'E:\\Work\\Dev\\\\q003207219\\root_dir\\file1']
    >>>
    >>> for entry in walk_generator:  # Display the rest of the elements (corresponding to every subdir)
    ...     print(entry)
    ...
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir0', ['dir00', 'dir01', 'dir02'], [])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir0\\dir00', ['dir000'], ['file000'])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir0\\dir00\\dir000', [], ['file0000'])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir0\\dir01', [], ['file010', 'file011'])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir0\\dir02', ['dir020'], [])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir0\\dir02\\dir020', ['dir0200'], [])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir0\\dir02\\dir020\\dir0200', [], [])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir1', [], ['file10', 'file11', 'file12'])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir2', ['dir20'], ['file20'])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir2\\dir20', [], ['file200'])
    ('E:\\Work\\Dev\\\\q003207219\\root_dir\\dir3', [], [])
    

    ملاحظات :

    • تحت الكواليس ، يستخدم os.listdir(os.scandir أينما متاح)
    • يفعل الرفع الثقيل عن طريق تكرار في المجلدات الفرعية


  1. [بيثون]: الكرة الأرضية. glob ( pathname، *، recursive = False ) ( [Python]: glob . iglob ( pathname، *، recursive = False ) )

    قم بإرجاع قائمة فارغة من أسماء المسارات التي تطابق اسم المسار ، والتي يجب أن تكون سلسلة تحتوي على مواصفات مسار. يمكن أن يكون اسم المسار إما مطلقًا (مثل /usr/src/Python-1.5/Makefile) أو نسبيًا (مثل ../../Tools/*/*.gif) ، ويمكن أن يحتوي على أحرف بدل نمط shell. يتم تضمين الارتباطات الرمزية المكسورة في النتائج (كما في shell).
    ...
    تم تغييره في الإصدار 3.5 : دعم لكرات متكررة باستخدام "**".


    >>> import glob, os
    >>> wildcard_pattern = "*"
    >>> root_dir = os.path.join("root_dir", wildcard_pattern)  # Match every file/dir name
    >>> root_dir
    'root_dir\\*'
    >>>
    >>> glob_list = glob.glob(root_dir)
    >>> glob_list
    ['root_dir\\dir0', 'root_dir\\dir1', 'root_dir\\dir2', 'root_dir\\dir3', 'root_dir\\file0', 'root_dir\\file1']
    >>>
    >>> [item.replace("root_dir" + os.path.sep, "") for item in glob_list]  # Strip the dir name and the path separator from begining
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> for entry in glob.iglob(root_dir + "*", recursive=True):
    ...     print(entry)
    ...
    root_dir\
    root_dir\dir0
    root_dir\dir0\dir00
    root_dir\dir0\dir00\dir000
    root_dir\dir0\dir00\dir000\file0000
    root_dir\dir0\dir00\file000
    root_dir\dir0\dir01
    root_dir\dir0\dir01\file010
    root_dir\dir0\dir01\file011
    root_dir\dir0\dir02
    root_dir\dir0\dir02\dir020
    root_dir\dir0\dir02\dir020\dir0200
    root_dir\dir1
    root_dir\dir1\file10
    root_dir\dir1\file11
    root_dir\dir1\file12
    root_dir\dir2
    root_dir\dir2\dir20
    root_dir\dir2\dir20\file200
    root_dir\dir2\file20
    root_dir\dir3
    root_dir\file0
    root_dir\file1
    

    ملاحظات :

    • الاستخدامات os.listdir
    • للأشجار الكبيرة (خاصة إذا كانت recursiveقيد التشغيل) ،iglob ويفضل
    • للسماح بالترشيح المتقدم استنادًا إلى الاسم (بسبب حرف البدل)


  1. [بيثون]: الطبقة مسار. المسار ( * pathsegments ) ( !!! Python 3 + !!! لا أعرف ما إذا كانت backported)

    >>> import pathlib
    >>> root_dir = "root_dir"
    >>> root_dir_instance = pathlib.Path(root_dir)
    >>> root_dir_instance
    WindowsPath('root_dir')
    >>> root_dir_instance.name
    'root_dir'
    >>> root_dir_instance.is_dir()
    True
    >>>
    >>> [item.name for item in root_dir_instance.glob("*")]  # Wildcard searching for all direct descendants
    ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [os.path.join(item.parent.name, item.name) for item in root_dir_instance.glob("*") if not item.is_dir()]  # Display paths (including parent) for files only
    ['root_dir\\file0', 'root_dir\\file1']
    

    ملاحظات :

    • هذه هي إحدى الطرق لتحقيق هدفنا
    • إنه أسلوب OOP في معالجة المسارات
    • يقدم الكثير من الوظائف


  1. [بيثون]: dircache.listdir (المسار) ( !!! إزالتها في بيثون 3 !!! )

    • ولكن ، وفقًا لـ $ {PYTHON_SRC_DIR} /Lib/dircache.py : ~ # 20 + (من v2.7.14 ) ، فهو مجرد غلاف (رفيع)os.listdir


    def listdir(path):
        """List directory contents, using cache."""
        try:
            cached_mtime, list = cache[path]
            del cache[path]
        except KeyError:
            cached_mtime, list = -1, []
        mtime = os.stat(path).st_mtime
        if mtime != cached_mtime:
            list = os.listdir(path)
            list.sort()
        cache[path] = mtime, list
        return list
    


  1. [man]: OPENDIR (3) / [man]: READDIR (3) / [man]: CLOSEDIR (3) via [Python]: ctypes - A function function library for Python ( !!! Ux specific !!! !!! )

    ctypes هي مكتبة وظيفة أجنبية لبيثون. يوفر أنواع البيانات المتوافقة مع C ، ويسمح بوظائف الاتصال في DLL أو المكتبات المشتركة. يمكن استخدامه لف هذه المكتبات في بيثون نقية.

    code_ctypes.py :

    #!/usr/bin/env python3
    
    import sys
    from ctypes import Structure, \
        c_ulonglong, c_longlong, c_ushort, c_ubyte, c_char, c_int, \
        CDLL, POINTER, \
        create_string_buffer, get_errno, set_errno, cast, sizeof
    
    
    DT_DIR = 4
    DT_REG = 8
    
    char256 = c_char * 256
    
    class LinuxDirent64(Structure):
        _fields_ = [
            ("d_ino", c_ulonglong),
            ("d_off", c_longlong),
            ("d_reclen", c_ushort),
            ("d_type", c_ubyte),
            ("d_name", char256),
        ]
    
    LinuxDirent64Ptr = POINTER(LinuxDirent64)
    
    libc_dll = CDLL(None)
    opendir = libc_dll.opendir
    readdir = libc_dll.readdir
    closedir = libc_dll.closedir
    libc_dll.__errno_location.restype = POINTER(c_int)
    errno_loc_func = libc_dll.__errno_location
    
    
    def _get_errno():
        return "errno: {:d}({:d})".format(get_errno(), errno_loc_func().contents.value)
    
    
    def get_dir_content(path):
        ret = [path, list(), list()]
        dir_stream = opendir(create_string_buffer(path.encode()))
        if (dir_stream == 0):
            print("opendir returned NULL ({:s})".format(_get_errno()))
            return ret
        set_errno(0)
        dirent_addr = readdir(dir_stream)
        while dirent_addr:
            dirent_ptr = cast(dirent_addr, LinuxDirent64Ptr)
            dirent = dirent_ptr.contents
            name = dirent.d_name.decode()
            if dirent.d_type & DT_DIR:
                if name not in (".", ".."):
                    ret[1].append(name)
            elif dirent.d_type & DT_REG:
                ret[2].append(name)
            dirent_addr = readdir(dir_stream)
        if get_errno() or errno_loc_func().contents.value:
            print("readdir returned NULL ({:s})".format(_get_errno()))
        closedir(dir_stream)
        return ret
    
    
    def main():
        print("{:s} on {:s}\n".format(sys.version, sys.platform))
        root_dir = "root_dir"
        entries = get_dir_content(root_dir)
        print(entries)
    
    
    if __name__ == "__main__":
        main()
    

    ملاحظات :

    • يقوم بتحميل الوظائف الثلاث من libc (المحملة في العملية الحالية) ويستدعيها (لمزيد من التفاصيل تحقق []: كيف أتحقق من وجود ملف باستخدام Python؟ (@ CristiFati's answer) - الملاحظات الأخيرة من البند رقم 4 . ). سيضع هذا النهج قريبًا جدًا من حافة بايثون / ج
    • LinuxDirent64هو تمثيل ctypesstruct dirent64 من dirent.h (وكذلك هي DT_*الثوابت) من الجهاز الخاص بي: Ubtu 16 x64 ( 4.10.0-40- general و libc6-dev: amd64 ). على النكهات / الإصدارات الأخرى ، قد يختلف تعريف البنية ، وإذا كان الأمر كذلك ، فيجب تحديث الاسم المستعار ctypes ، وإلا فإنه سيؤدي إلى سلوك غير محدد
    • errno_loc_func(وكل ما يتعلق بها) هو لأن funcs تعيين errnoفي حالة الخطأ ، ولست بحاجة للتحقق من قيمتها. على ما يبدو ، get_errnoلا يعمل (مع اسم غير صالح ، opendirيعود NULL، ولكنget_errno لا يزال يعود 0) ، أو لم أجده بعد
    • تقوم بإرجاع البيانات في os.walk بتنسيق. لم أكن أزعج أن أجعلها تعاودية ، ولكن بدءا من الكود الحالي ، ستكون مهمة تافهة إلى حد ما
    • كل شيء قابل للتنفيذ على وين كذلك ، البيانات (المكتبات ، الوظائف ، البنى ، الثوابت ، ...) تختلف


    الإخراج :

    [email protected]:~/work//q003207219$ ./code_ctypes.py
    3.5.2 (default, Nov 23 2017, 16:37:01)
    [GCC 5.4.0 20160609] on linux
    
    ['root_dir', ['dir3', 'dir2', 'dir0', 'dir1'], ['file0', 'file1']]
    


  1. [ActiveState]: win32file.FindFilesW ( !!! الفوز محددة !!! )

    استرداد قائمة بأسماء الملفات المطابقة ، باستخدام Windows Unicode API. واجهة إلى وظائف إغلاق API FindFirstFileW / FindNextFileW / بحث.


    >>> import os, win32file, win32con
    >>> root_dir = "root_dir"
    >>> wildcard = "*"
    >>> root_dir_wildcard = os.path.join(root_dir, wildcard)
    >>> entry_list = win32file.FindFilesW(root_dir_wildcard)
    >>> len(entry_list)  # Don't display the whole content as it's too long
    8
    >>> [entry[-2] for entry in entry_list]  # Only display the entry names
    ['.', '..', 'dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1']
    >>>
    >>> [entry[-2] for entry in entry_list if entry[0] & win32con.FILE_ATTRIBUTE_DIRECTORY and entry[-2] not in (".", "..")]  # Filter entries and only display dir names (except self and parent)
    ['dir0', 'dir1', 'dir2', 'dir3']
    >>>
    >>> [os.path.join(root_dir, entry[-2]) for entry in entry_list if entry[0] & (win32con.FILE_ATTRIBUTE_NORMAL | win32con.FILE_ATTRIBUTE_ARCHIVE)]  # Only display file "full" names
    ['root_dir\\file0', 'root_dir\\file1']
    

    ملاحظات :


  1. قم بتثبيت حزمة (أخرى) تابعة لجهة خارجية تقوم بهذه المهمة
    • على الأرجح ، يعتمد على واحد (أو أكثر) من أعلاه (ربما مع تخصيصات طفيفة)


ملاحظات (حول الأشياء المذكورة أعلاه):

  • من المفترض أن تكون الشفرة محمولة (باستثناء الأماكن التي تستهدف منطقة معينة - والتي تم وضع علامة عليها) أو عبر:
    • منصة ( Ux ، Win ،)
    • نسخة بايثون (2 ، 3 ،)
  • تم استخدام أنماط المسارات المتعددة (المطلقة ، الأقارب) عبر المتغيرات المذكورة أعلاه ، لتوضيح حقيقة أن "الأدوات" المستخدمة مرنة في هذا الاتجاه
  • os.listdirو os.scandirاستخدام opendir/ readdir/ closedir( [MSDN]: FindFirstFile وظيفة / [MSDN]: FindNextFile وظيفة / [MSDN]: وظيفة FindClose ) (عبر " $ {PYTHON_SRC_DIR} /Modules/posixmodule.c ")
  • win32file.FindFilesWيستخدم هذه الوظائف ( الخاصة بـ Win المحددة) أيضًا (عبر " $ {PYWIN32_SRC_DIR} /win32/src/win32file.i ")
  • get_dir_content(من النقطة رقم 1. ) يمكن تنفيذها باستخدام أي من هذه الأساليب (بعضها يتطلب المزيد من العمل وبعض أقل)
    • يمكن إجراء بعض التصفية المتقدمة (بدلاً من مجرد ملف مقابل dir): على سبيل المثال include_foldersيمكن استبدال الحجة بواحدة أخرى (على سبيل المثال filter_func) والتي ستكون دالة تأخذ مسارًا كحجة: filter_func=lambda x: True(هذا لا يزيل أي شيء) وداخل get_dir_contentشيء ما مثل: if not filter_func(entry_with_path): continue(في حالة فشل الوظيفة لإدخال واحد ، سيتم تخطيها) ، ولكن كلما ازدادت تعقيدات الشفرة ، كلما تطلب الأمر وقتًا أطول لتنفيذها
  • نوتا بيني! منذ استخدام العودية ، يجب أن أذكر أنني أجريت بعض الاختبارات على جهاز الكمبيوتر المحمول الخاص بي ( Win 10 x64 ) ، غير مرتبط تمامًا بهذه المشكلة ، وعندما وصل مستوى العودية إلى قيم في مكان ما في النطاق (990 .. 1000) ( recursionlimit - 1000) (افتراضي)) ، حصلت على :). إذا تجاوزت شجرة الدليل هذا الحد (لست خبيرًا في FS ، لذا لا أعرف ما إذا كان ذلك ممكنًا) ، فقد يكون ذلك مشكلة.
    يجب أن أذكر أيضا أنني لم أحاول زيادة مستوى recursionlimit لأنه ليس لدي أي خبرة في المنطقة (كم يمكنني زيادة ذلك قبل الاضطرار إلى زيادة أيضا كومة في نظام التشغيل ، ولكن من الناحية النظرية سيكون هناك دائما احتمال الفشل ، إذا كان عمق دير أكبر من أعلى recursionlimit ممكن (على هذا الجهاز)
  • نماذج التعليمات البرمجية هي لأغراض العرض فقط. وهذا يعني أنني لم أضع في الاعتبار معالجة الأخطاء (لا أعتقد أن هناك أي try/ except/ else/ finallyحظر) ، وبالتالي فإن الشفرة ليست قوية (والسبب هو: الاحتفاظ بها بسيطة وقصيرة قدر الإمكان). لل إنتاج ، يجب إضافة معالجة الأخطاء، وكذلك

نهاية الجزء الأول 1


1. يرجع ذلك إلى حقيقة أن الحد الأقصى لنسبة Home (السؤال / الإجابة) هو 30000 حرف ( [SE.Meta]: معرفة حدودك: ما هو الحد الأقصى لطول عنوان السؤال ، والبريد ، والصورة ، والروابط المستخدمة؟ ) ، تم تقسيم الإجابة على جزئين. يرجى أيضًا زيارة [SO]: كيف أقوم بإدراج جميع ملفات الدليل؟ (@ CristiFati's إجابة - "الجزء الثاني") .


منذ الإصدار 3.4 هناك os.listdir() أكثر كفاءة من os.listdir() :

pathlib : الجديد في الإصدار 3.4.

>>> import pathlib
>>> [p for p in pathlib.Path('.').iterdir() if p.is_file()]

ووفقًا لـ PEP 428 ، تهدف مكتبة pathlib إلى توفير تسلسل هرمي بسيط للفصول للتعامل مع مسارات نظام الملفات وعمليات المستخدمين الشائعة التي يقومون بها.

os.scandir() : الجديد في الإصدار 3.5.

>>> import os
>>> [entry for entry in os.scandir('.') if entry.is_file()]

لاحظ أن os.walk() يستخدم os.scandir() بدلاً من os.listdir() من الإصدار 3.5 ، وقد زادت سرعته من 2 إلى 20 مرة طبقًا لـ PEP 471 .

دعني أوصي أيضًا بقراءة تعليق ShadowRanger أدناه.


عودة قائمة الملفات filepaths المطلقة ، لا تتكرر في الدلائل الفرعية

L = [os.path.join(os.getcwd(),f) for f in os.listdir('.') if os.path.isfile(os.path.join(os.getcwd(),f))]

import os
import os.path


def get_files(target_dir):
    item_list = os.listdir(target_dir)

    file_list = list()
    for item in item_list:
        item_dir = os.path.join(target_dir,item)
        if os.path.isdir(item_dir):
            file_list += get_files(item_dir)
        else:
            file_list.append(item_dir)
    return file_list

هنا أنا استخدم بنية متكررة.


أنا حقا أحب إجابة adamk ، مما يوحي بأنك تستخدم glob() ، من الوحدة النمطية التي تحمل الاسم نفسه. يتيح لك ذلك مطابقة النمط مع * s.

ولكن كما أشار أشخاص آخرون في التعليقات ، يمكن تعثر glob() فوق اتجاهات القطع غير المتسقة. للمساعدة في ذلك ، أقترح عليك استخدام الدالات join() و expanduser() في الوحدة os.path ، وربما getcwd() في وحدة os ، كذلك.

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

from glob import glob

# Return everything under C:\Users\admin that contains a folder called wlp.
glob('C:\Users\admin\*\wlp')

ما سبق هو فظيع - المسار قد تم ضمنية وستعمل فقط على ويندوز بين اسم محرك الأقراص و \ s يجري hardcoded في المسار.

from glob    import glob
from os.path import join

# Return everything under Users, admin, that contains a folder called wlp.
glob(join('Users', 'admin', '*', 'wlp'))

يعمل أعلاه بشكل أفضل ، لكنه يعتمد على اسم المجلد Users الذي غالبا ما يتم العثور عليه على Windows ولا يتم العثور عليه في كثير من الأحيان على أنظمة تشغيل أخرى. كما يعتمد على المستخدم الذي يحمل اسمًا محددًا ، وهو admin .

from glob    import glob
from os.path import expanduser, join

# Return everything under the user directory that contains a folder called wlp.
glob(join(expanduser('~'), '*', 'wlp'))

هذا يعمل بشكل مثالي عبر جميع المنصات.

مثال رائع آخر يعمل بشكل مثالي عبر الأنظمة الأساسية ويفعل شيئًا مختلفًا:

from glob    import glob
from os      import getcwd
from os.path import join

# Return everything under the current directory that contains a folder called wlp.
glob(join(getcwd(), '*', 'wlp'))

نأمل أن تساعدك هذه الأمثلة في رؤية قوة عدد قليل من الوظائف التي يمكنك العثور عليها في وحدات برامج مكتبة Python القياسية.


# -** coding: utf-8 -*-
import os
import traceback

print '\n\n'

def start():
    address = "/home/ubuntu/Desktop"
    try:
        Folders = []
        Id = 1
        for item in os.listdir(address):
            endaddress = address + "/" + item
            Folders.append({'Id': Id, 'TopId': 0, 'Name': item, 'Address': endaddress })
            Id += 1         

            state = 0
            for item2 in os.listdir(endaddress):
                state = 1
            if state == 1: 
                Id = FolderToList(endaddress, Id, Id - 1, Folders)
        return Folders
    except:
        print "___________________________ ERROR ___________________________\n" + traceback.format_exc()

def FolderToList(address, Id, TopId, Folders):
    for item in os.listdir(address):
        endaddress = address + "/" + item
        Folders.append({'Id': Id, 'TopId': TopId, 'Name': item, 'Address': endaddress })
        Id += 1

        state = 0
        for item in os.listdir(endaddress):
            state = 1
        if state == 1: 
            Id = FolderToList(endaddress, Id, Id - 1, Folders)
    return Id

print start()

باستخدام المولدات

# python 2.x
import scandir
import sys

de = scandir.scandir(sys.argv[1])
while 1:
    try:
        d = de.next()
        print d.path
    except StopIteration as _:
        break

filenames = next(os.walk(path))[2]

هذا سيعود قائمة بجميع الملفات والدلائل في path.

import os
for root, dirs,files in os.walk("your dir path", topdown=True):
    for name in files:
        print(os.path.join(root, name))

سيؤدي هذا إلى إرجاع قائمة الملفات فقط ، وليس الدلائل الفرعية.


بالإشارة إلى إجابةadamk ، إليك طريقة اكتشاف نظام التشغيل os استجابةً لملاحظة عدم التناسق المائل لـAnti Earth

from pathlib import Path
folder = '/foo'
[f for f in Path(folder).glob('*') if f.is_file()]
[f for f in Path(folder).glob('**/*.py') if not f.is_symlink()]

أفترض أنك تريد فقط basenames في القائمة.

ارجع إلى هذه post لتحديد تنسيقات ملفات متعددة مسبقًا للطريقة 1.


الحصول على كامل مسارات الملفات من دليل وجميع الأدلة الفرعية

import os

def get_filepaths(directory):
    """
    This function will generate the file names in a directory 
    tree by walking the tree either top-down or bottom-up. For each 
    directory in the tree rooted at directory top (including top itself), 
    it yields a 3-tuple (dirpath, dirnames, filenames).
    """
    file_paths = []  # List which will store all of the full filepaths.

    # Walk the tree.
    for root, directories, files in os.walk(directory):
        for filename in files:
            # Join the two strings in order to form the full filepath.
            filepath = os.path.join(root, filename)
            file_paths.append(filepath)  # Add it to the list.

    return file_paths  # Self-explanatory.

# Run the above function and store its results in a variable.   
full_file_paths = get_filepaths("/Users/johnny/Desktop/TEST")
  • يحتوي المسار الذي قدمته في الدالة أعلاه على 3 ملفات - اثنتان منها في الدليل الجذر ، وأخرى في مجلد فرعي يسمى "SUBFOLDER". يمكنك الآن القيام بأشياء مثل:
  • print full_file_paths التي ستطبع القائمة:

    • ['/Users/johnny/Desktop/TEST/file1.txt', '/Users/johnny/Desktop/TEST/file2.txt', '/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat']

إذا كنت ترغب في ذلك ، يمكنك فتح المحتويات وقراءتها ، أو التركيز فقط على الملفات ذات الامتداد ".dat" كما في التعليمة البرمجية أدناه:

for f in full_file_paths:
  if f.endswith(".dat"):
    print f

/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat


تنفيذ findfiles () مع دليل كمعلمة وسيعود قائمة بكل الملفات الموجودة فيه.

import sys
import os
from pathlib import Path
from glob import glob
platformtype = sys.platform
if platformtype == 'win32':
    slash = "\\"
if platformtype == 'darwin':
    slash = "/"

# TODO: How can I list all files of a directory in Python and add them to a list?

# Step 1 - List all files of a directory

# Method 1: Find only pre-defined filetypes (.txt) and no subfiles, answer provided by @adamk
dir1 = "%sfoo%sbar%s*.txt" % (slash)
_files = glob(dir1)

# Method 2: Find all files and no subfiles
dir2 = "%sfoo%sbar%s" % (slash)
_files = (x for x in Path("dir2").iterdir() if x.is_file())

# Method 3: Find all files and all subfiles
dir3 = "%sfoo%sbar" % (slash)
_files = (x for x in Path('dir3').glob('**/*') if x.is_file())


# Step 2 - Add them to a list

files_list = []
for eachfiles in _files:
    files_basename = os.path.basename(eachfiles)
    files_list.append(files_basename)

يجب عليك استخدام وحدة os لإدراج محتوى الدليل. os.listdir(".") بإرجاع كل محتويات الدليل. نحن نكرر النتيجة ونضيفها إلى القائمة.

import os

content_list = []

for content in os.listdir("."): # "." means current directory
    content_list.append(content)

print content_list

هناك متغير آخر قابل للقراءة جدًا لـ Python 3.4 أو أحدث يستخدم pathlib.Path.glob:

print(files_list)
['file1.txt', 'file2.txt', .... ]

من السهل أن تكون أكثر تحديدًا ، على سبيل المثال ، فقط ابحث عن ملفات مصدر بايثون التي ليست روابط رمزية ، أيضًا في جميع الدلائل الفرعية:

import os
[f for f in os.listdir(os.getcwd) if ...]

أفترض أن جميع ملفاتك ذات *.txtتنسيق ، ويتم تخزينها داخل مجلد بمسار data/.

يمكن للمرء استخدام الوحدة النمطية للكرة الأرضيةpython لسرد كافة ملفات الدليل وإضافتها إلى قائمة مسماة fnames، بالطريقة التالية:

import dircache
list = dircache.listdir(pathname)
i = 0
check = len(list[0])
temp = []
count = len(list)
while count != 0:
  if len(list[i]) != check:
     temp.append(list[i-1])
     check = len(list[i])
  else:
    i = i + 1
    count = count - 1

print temp

أرى إجابتين لهما صفات جيدة ، كل منهما به عيب صغير ، لذا سأعطيه الأمر:

حاول os.path.exists ، والنظر os.makedirs للإبداع.

import os
if not os.path.exists(directory):
    os.makedirs(directory)

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

قد يكون أحد الخيارات هو اعتراض OSError وفحص رمز الخطأ المضمن (راجع هل هناك طريقة عبر النظام الأساسي للحصول على معلومات من OSError Python ):

import os, errno

try:
    os.makedirs(directory)
except OSError as e:
    if e.errno != errno.EEXIST:
        raise

بدلاً من ذلك ، يمكن أن يكون هناك os.path.exists ثانيًا ، لكن لنفترض أن آخرًا أنشأ الدليل بعد التحقق الأول ، ثم os.path.exists الثاني - لا يزال من الممكن خداعنا.

اعتمادا على التطبيق ، قد يكون خطر العمليات المتزامنة أكثر أو أقل من الخطر الذي تشكله عوامل أخرى مثل أذونات الملفات. سيتعين على المطور معرفة المزيد عن التطبيق المعين الذي يجري تطويره وبيئة العمل المتوقعة قبل اختيار التنفيذ.





python directory