كيفية الحصول على جميع الدلائل الفرعية المباشرة في بايثون
سؤال
أحاول كتابة برنامج نصي بسيط من نوع 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')