كيفية إدراج أدلة المستوى الأعلى فقط في بايثون؟

StackOverflow https://stackoverflow.com/questions/141291

  •  02-07-2019
  •  | 
  •  

سؤال

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

دعونا نرى ما إذا كان المثال يساعد.في الدليل الحالي لدينا:

>>> os.listdir(os.getcwd())
['cx_Oracle-doc', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'LICENSE.txt', 'mod_p
ython-wininst.log', 'NEWS.txt', 'pymssql-wininst.log', 'python.exe', 'pythonw.ex
e', 'README.txt', 'Removemod_python.exe', 'Removepymssql.exe', 'Scripts', 'tcl',
 'Tools', 'w9xpopen.exe']

ومع ذلك، لا أريد إدراج أسماء الملفات.ولا أريد مجلدات فرعية مثل \Lib\curses.في الأساس ما أريده يعمل مع ما يلي:

>>> for root, dirnames, filenames in os.walk('.'):
...     print dirnames
...     break
...
['cx_Oracle-doc', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'Scripts', 'tcl', 'Tools']

ومع ذلك، أنا أتساءل عما إذا كانت هناك طريقة أبسط لتحقيق نفس النتائج.لدي انطباع بأن استخدام os.walk فقط لإعادة المستوى الأعلى هو أمر غير فعال/أكثر من اللازم.

هل كانت مفيدة؟

المحلول

قم بتصفية النتيجة باستخدام os.path.isdir() (واستخدم os.path.join() للحصول على المسار الحقيقي):

>>> [ name for name in os.listdir(thedir) if os.path.isdir(os.path.join(thedir, name)) ]
['ctypes', 'distutils', 'encodings', 'lib-tk', 'config', 'idlelib', 'xml', 'bsddb', 'hotshot', 'logging', 'doc', 'test', 'compiler', 'curses', 'site-packages', 'email', 'sqlite3', 'lib-dynload', 'wsgiref', 'plat-linux2', 'plat-mac']

نصائح أخرى

os.walk

يستخدم os.walk مع next وظيفة العنصر:

next(os.walk('.'))[1]

ل بايثون <=2.5 يستخدم:

os.walk('.').next()[1]

كيف يعمل هذا

os.walk هو مولد والدعوة next سوف تحصل على النتيجة الأولى في شكل 3-tuple (dirpath، dirnames، أسماء الملفات).وهكذا [1] يُرجع الفهرس فقط dirnames من تلك الطية.

قم بتصفية القائمة باستخدام os.path.isdir لاكتشاف الدلائل.

filter(os.path.isdir, os.listdir(os.getcwd()))
directories=[d for d in os.listdir(os.getcwd()) if os.path.isdir(d)]

لاحظ أنه بدلا من القيام به os.listdir(os.getcwd()), ، فمن الأفضل أن تفعل os.listdir(os.path.curdir).استدعاء وظيفة أقل، وهو محمول أيضًا.

لذا، لإكمال الإجابة، للحصول على قائمة بالأدلة في مجلد:

def listdirs(folder):
    return [d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d))]

إذا كنت تفضل أسماء المسارات الكاملة، فاستخدم هذه الوظيفة:

def listdirs(folder):
    return [
        d for d in (os.path.join(folder, d1) for d1 in os.listdir(folder))
        if os.path.isdir(d)
    ]

فقط لإضافة أن استخدام os.listdir() لا يفعل ذلك "يستغرق الكثير من المعالجة مقابل os.walk().next()[1] البسيط جدًا".وذلك لأن os.walk() يستخدم os.listdir() داخليًا.في الواقع، إذا قمت باختبارهم معًا:

>>>> import timeit
>>>> timeit.timeit("os.walk('.').next()[1]", "import os", number=10000)
1.1215229034423828
>>>> timeit.timeit("[ name for name in os.listdir('.') if os.path.isdir(os.path.join('.', name)) ]", "import os", number=10000)
1.0592019557952881

تصفية os.listdir() أسرع قليلاً جدًا.

هناك طريقة أبسط وأنيقة للغاية وهي استخدام هذا:

 import os
 dir_list = os.walk('.').next()[1]
 print dir_list

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

يبدو أن هذا يعمل أيضًا (على الأقل على نظام التشغيل Linux):

import glob, os
glob.glob('*' + os.path.sep)

كوني مبتدئًا هنا، لا يمكنني التعليق بشكل مباشر بعد ولكن إليك تصحيحًا صغيرًا أود إضافته إلى الجزء التالي من إجابة ΤΖΩΤΖΙΟΥ :

إذا كنت تفضل أسماء المسارات الكاملة، فاستخدم هذه الوظيفة:

def listdirs(folder):  
  return [
    d for d in (os.path.join(folder, d1) for d1 in os.listdir(folder))
    if os.path.isdir(d)
]

لأولئك الذين ما زالوا يستخدمون لغة بايثون <2.4:يجب أن يكون البناء الداخلي عبارة عن قائمة بدلاً من صف، وبالتالي يجب أن يُقرأ على النحو التالي:

def listdirs(folder):  
  return [
    d for d in [os.path.join(folder, d1) for d1 in os.listdir(folder)]
    if os.path.isdir(d)
  ]

وإلا فسيحصل على خطأ في بناء الجملة.

باستخدام فهم القائمة،

[a for a in os.listdir() if os.path.isdir(a)]

أعتقد أنها أبسط طريقة

[x for x in os.listdir(somedir) if os.path.isdir(os.path.join(somedir, x))]

للحصول على قائمة بأسماء المسارات الكاملة أفضّل هذا الإصدار على الإصدار الآخر حلول هنا:

def listdirs(dir):
    return [os.path.join(os.path.join(dir, x)) for x in os.listdir(dir) 
        if os.path.isdir(os.path.join(dir, x))]
scanDir = "abc"
directories = [d for d in os.listdir(scanDir) if os.path.isdir(os.path.join(os.path.abspath(scanDir), d))]

خيار أكثر أمانًا لا يفشل في حالة عدم وجود دليل.

def listdirs(folder):
    if os.path.exists(folder):
         return [d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d))]
    else:
         return []

مثل ذلك؟

>>>> [path for path in os.listdir(os.getcwd()) if os.path.isdir(path)]
-- This will exclude files and traverse through 1 level of sub folders in the root

def list_files(dir):
    List = []
    filterstr = ' '
    for root, dirs, files in os.walk(dir, topdown = True):
        #r.append(root)
        if (root == dir):
            pass
        elif filterstr in root:
            #filterstr = ' '
            pass
        else:
            filterstr = root
            #print(root)
            for name in files:
                print(root)
                print(dirs)
                List.append(os.path.join(root,name))
            #print(os.path.join(root,name),"\n")
                print(List,"\n")

    return List
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top