كيفية الحصول على جميع الدلائل الفرعية المباشرة في بايثون

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

  •  03-07-2019
  •  | 
  •  

سؤال

أحاول كتابة برنامج نصي بسيط من نوع Python يقوم بنسخ ملف Index.tpl إلى ملف Index.html في جميع الدلائل الفرعية (مع بعض الاستثناءات).

لقد تعثرت في محاولة الحصول على قائمة الدلائل الفرعية.

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

المحلول

import os
def get_immediate_subdirectories(a_dir):
    return [name for name in os.listdir(a_dir)
            if os.path.isdir(os.path.join(a_dir, name))]

نصائح أخرى

لماذا لا يذكر أحد glob ؟ glob يتيح لك استخدام توسيع مسار على غرار يونكس، وهي لغتي الذهاب للعمل في كل شيء تقريبا التي تحتاج إلى العثور على اسم أكثر من مسار واحد. انه يجعل من السهل جدا:

from glob import glob
paths = glob('*/')

وتجدر الإشارة إلى أن glob إرجاع الدليل مع الخط المائل النهائي (كما يونكس سوف) في حين أن معظم الحلول القائمة path سوف يحذف مائلة للنهائي.

وتحقق " الحصول على قائمة كل الدلائل في الدليل الحالي ".

وهنا نسخة بيثون 3:

import os

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

print(dir_list)
import os, os.path

للحصول على الدلائل الفرعية المباشرة (المسار الكامل) في الدليل:

def SubDirPath (d):
    return filter(os.path.isdir, [os.path.join(d,f) for f in os.listdir(d)])

للحصول على الدليل الفرعي الأحدث (الأحدث):

def LatestDirectory (d):
    return max(SubDirPath(d), key=os.path.getmtime)

os.walk هو صديقك في هذا الوضع.

ومباشرة من وثائق:

<اقتباس فقرة>   

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

وهذه الطريقة بشكل جيد يفعل كل شيء دفعة واحدة.

from glob import glob
subd = [s.rstrip("/") for s in glob(parent_dir+"*/")]

وعن طريق وحدة أسم دليل ملتوية ل:

from twisted.python.filepath import FilePath

def subdirs(pathObj):
    for subpath in pathObj.walk():
        if subpath.isdir():
            yield subpath

if __name__ == '__main__':
    for subdir in subdirs(FilePath(".")):
        print "Subdirectory:", subdir

وبما أن طلب بعض المعلقين ما مزايا استخدام المكتبات ملتوية لهذا، سأذهب قليلا أبعد من السؤال الأصلي هنا.


وهناك بعض تحسين الوثائق في الفرع الذي يوضح مزايا أسم دليل. قد ترغب في قراءة ذلك.

وبشكل أكثر تحديدا في هذا المثال: على عكس نسخة مكتبة القياسية، ويمكن أن تنفذ هذه الوظيفة مع أي واردات . وظيفة "دليل فرعي" هو عام تماما، حيث أنه يعمل على أي شيء ولكن حجتها. من أجل نسخ ونقل الملفات باستخدام المكتبة القياسية، تحتاج إلى الاعتماد على المضمن "open"، "listdir"، وربما "isdir" أو "os.walk" أو "shutil.copy". ربما "os.path.join" أيضا. ناهيك عن حقيقة أن تحتاج مرت سلسلة حجة لتحديد الملف الفعلي. دعونا نلقي نظرة على التنفيذ الكامل التي سوف نسخ كل دليل "index.tpl" إلى "index.html و":

def copyTemplates(topdir):
    for subdir in subdirs(topdir):
        tpl = subdir.child("index.tpl")
        if tpl.exists():
            tpl.copyTo(subdir.child("index.html"))

وظيفة "دليل فرعي" أعلاه يمكن أن يعمل على أي كائن مثل FilePath. وهو ما يعني، من بين أمور أخرى، وكائنات ZipPath. للأسف ZipPath للقراءة فقط في الوقت الحالي، ولكن يمكن أن تمتد إلى دعم الكتابة.

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

class MyFakePath:
    def child(self, name):
        "Return an appropriate child object"

    def walk(self):
        "Return an iterable of MyFakePath objects"

    def exists(self):
        "Return true or false, as appropriate to the test"

    def isdir(self):
        "Return true or false, as appropriate to the test"
...
subdirs(MyFakePath(...))

ولقد كتب بعض رمز للتحرك الأجهزة الظاهرية وير حولها، وانتهى الأمر باستخدام os.path وshutil لإنجاز نسخ الملفات بين الدلائل الفرعية.

def copy_client_files (file_src, file_dst):
    for file in os.listdir(file_src):
            print "Copying file: %s" % file
            shutil.copy(os.path.join(file_src, file), os.path.join(file_dst, file))

وانها ليست أنيقة بشكل رهيب، ولكن هل العمل.

إليك طريقة واحدة:

import os
import shutil

def copy_over(path, from_name, to_name):
  for path, dirname, fnames in os.walk(path):
    for fname in fnames:
      if fname == from_name:
        shutil.copy(os.path.join(path, from_name), os.path.join(path, to_name))


copy_over('.', 'index.tpl', 'index.html')
def get_folders_in_directories_recursively(self, directory, index=0):
    folder_list = list()
    parent_directory = directory

    for path, subdirs, _ in os.walk(directory):
        if not index:
            for sdirs in subdirs:
                folder_path = "{}/{}".format(path, sdirs)
                folder_list.append(folder_path)
        elif path[len(parent_directory):].count('/') + 1 == index:
            for sdirs in subdirs:
                folder_path = "{}/{}".format(path, sdirs)
                folder_list.append(folder_path)

    return folder_list

ويمكن استدعاء الدالة التالية على النحو التالي:

وget_folders_in_directories_recursively (دليل ومؤشر = 1) -> يعطي قائمة المجلدات في المستوى الأول

وget_folders_in_directories_recursively (الدليل) -> يعطي كل المجلدات الفرعية

ويجب أن أذكر أن path.py مكتبة، الذي استعمل في كثير من الأحيان.

وجلب والدلائل المباشرة أصبحت بسيطة على هذا النحو:

وmy_dir.dirs()

والمثال العمل الكامل هو:

from path import Path

my_directory = Path("path/to/my/directory")

subdirs = my_directory.dirs()
<اقتباس فقرة>   

ملاحظة: my_directory لا يزال من الممكن التلاعب كسلسلة، منذ Path هو فئة فرعية من سلسلة، ولكن توفر مجموعة من أساليب مفيدة لمعالجة مسارات

import glob
import os

def child_dirs(path):
     cd = os.getcwd()        # save the current working directory
     os.chdir(path)          # change directory 
     dirs = glob.glob("*/")  # get all the subdirectories
     os.chdir(cd)            # change directory to the script original location
     return dirs

وظيفة child_dirs يأخذ مسار دليل وإرجاع قائمة الدلائل المباشرة في ذلك.

dir
 |
  -- dir_1
  -- dir_2

child_dirs('dir') -> ['dir_1', 'dir_2']
import pathlib


def list_dir(dir):
    path = pathlib.Path(dir)
    dir = []
    try:
        for item in path.iterdir():
            if item.is_dir():
                dir.append(item)
        return dir
    except FileNotFoundError:
        print('Invalid directory')
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top