আমি একটি সাধারণ পাইথন স্ক্রিপ্ট লেখার চেষ্টা করছি যা সমস্ত উপ-ডিরেক্টরিতে (কয়েকটি ব্যতিক্রম বাদে) একটি সূচি.টি.পি.এল.কে সূচক। Html অনুলিপি করবে।
আমি উপ-ডিরেক্টরিগুলির তালিকা পাওয়ার চেষ্টা করে জড়িয়ে যাচ্ছি।
আমি একটি সাধারণ পাইথন স্ক্রিপ্ট লেখার চেষ্টা করছি যা সমস্ত উপ-ডিরেক্টরিতে (কয়েকটি ব্যতিক্রম বাদে) একটি সূচি.টি.পি.এল.কে সূচক। Html অনুলিপি করবে।
আমি উপ-ডিরেক্টরিগুলির তালিকা পাওয়ার চেষ্টা করে জড়িয়ে যাচ্ছি।
উত্তর:
সমস্ত বর্তমান উপ-ডিরেক্টরিতে পুরো পথটি ফিরিয়ে আনতে আমি বিভিন্ন ক্রিয়ায় কিছু গতি পরীক্ষা করেছি ।
tl; dr:
সর্বদা ব্যবহার করুন scandir
:
list_subfolders_with_paths = [f.path for f in os.scandir(path) if f.is_dir()]
বোনাস: scandir
আপনি কেবল কেবল f.name
পরিবর্তে ব্যবহার করে ফোল্ডারের নামগুলি পেতে পারেন f.path
।
এটি (পাশাপাশি নীচে অন্যান্য সমস্ত ফাংশন) প্রাকৃতিক বাছাই ব্যবহার করবে না । এর অর্থ ফলাফলগুলি এইভাবে সাজানো হবে: 1, 10, 2। প্রাকৃতিক বাছাই পেতে (1, 2, 10), দয়া করে একবার দেখুন https://stackoverflow.com/a/48030307/2441026
ফলাফল : এর
scandir
চেয়ে 3x দ্রুত walk
, listdir
(ফিল্টার সহ) 32x দ্রুত , 35x এর চেয়ে দ্রুত Pathlib
এবং 36x এর চেয়ে দ্রুত listdir
এবং 37x (!) এর চেয়ে দ্রুত glob
।
Scandir: 0.977
Walk: 3.011
Listdir (filter): 31.288
Pathlib: 34.075
Listdir: 35.501
Glob: 36.277
ডাব্লু 7x64, পাইথন 3.8.1 এর সাথে পরীক্ষিত। 440 সাবফোল্ডার সহ ফোল্ডার।
আপনি যদি ভাবছেন যে listdir
os.path.join () দু'বার না করে গতি বাড়ানো যায় তবে হ্যাঁ, তবে পার্থক্যটি মূলত অস্তিত্বহীন।
কোড:
import os
import pathlib
import timeit
import glob
path = r"<example_path>"
def a():
list_subfolders_with_paths = [f.path for f in os.scandir(path) if f.is_dir()]
# print(len(list_subfolders_with_paths))
def b():
list_subfolders_with_paths = [os.path.join(path, f) for f in os.listdir(path) if os.path.isdir(os.path.join(path, f))]
# print(len(list_subfolders_with_paths))
def c():
list_subfolders_with_paths = []
for root, dirs, files in os.walk(path):
for dir in dirs:
list_subfolders_with_paths.append( os.path.join(root, dir) )
break
# print(len(list_subfolders_with_paths))
def d():
list_subfolders_with_paths = glob.glob(path + '/*/')
# print(len(list_subfolders_with_paths))
def e():
list_subfolders_with_paths = list(filter(os.path.isdir, [os.path.join(path, f) for f in os.listdir(path)]))
# print(len(list(list_subfolders_with_paths)))
def f():
p = pathlib.Path(path)
list_subfolders_with_paths = [x for x in p.iterdir() if x.is_dir()]
# print(len(list_subfolders_with_paths))
print(f"Scandir: {timeit.timeit(a, number=1000):.3f}")
print(f"Listdir: {timeit.timeit(b, number=1000):.3f}")
print(f"Walk: {timeit.timeit(c, number=1000):.3f}")
print(f"Glob: {timeit.timeit(d, number=1000):.3f}")
print(f"Listdir (filter): {timeit.timeit(e, number=1000):.3f}")
print(f"Pathlib: {timeit.timeit(f, number=1000):.3f}")
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
ভিত্তিক সমাধান চূড়ান্ত স্ল্যাশ বাদ দেবে।
paths = [ p.replace('/', '') for p in glob('*/') ]
।
[p[:-1] for p in paths]
, কারণ এই প্রতিস্থাপন পদ্ধতিটি ফাইলের নামের কোনও পালানো ফরোয়ার্ড স্ল্যাশগুলি প্রতিস্থাপন করবে (এটি সাধারণ নয়) common
rstrip
পরিবর্তে অবশ্যই ব্যবহার করতে চান strip
, যেহেতু পরেরগুলি কোনও সম্পূর্ণ যোগ্য পাথকে আপেক্ষিক পথে পরিণত করবে।
strip('/')
'/' শুরু করা এবং অনুসরণ করা উভয়ই সরিয়ে ফেলব , rstrip('/')
কেবল অনুসরণকারীটিকে সরিয়ে ফেলবে
" বর্তমান ডিরেক্টরিতে সমস্ত উপ-ডিরেক্টরিগুলির একটি তালিকা পাওয়া " পরীক্ষা করুন।
এখানে পাইথন 3 সংস্করণ রয়েছে:
import os
dir_list = next(os.walk('.'))[1]
print(dir_list)
(s.rstrip("/") for s in glob(parent_dir+"*/"))
আরও সময় দক্ষ কিনা তা সম্পর্কে আমি আগ্রহী । আমার স্বজ্ঞাত সন্দেহ করে একটি হল stat()
ভিত্তিক os.walk()
সমাধান করা উচিত গভীর দ্রুত শেল-শৈলী globbing চেয়ে। দুঃখের বিষয়, আমার ইচ্ছাশক্তি নেই timeit
এবং প্রকৃতপক্ষে এটি সন্ধান করতে পারি।
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)
list( filter(...) )
।
os.walk
এই পরিস্থিতিতে আপনার বন্ধু।
ডকুমেন্টেশন থেকে সরাসরি:
ওয়াক () ডিরেক্টরিটিকে নীচে বা নীচে উপরের দিকে হাঁটার মাধ্যমে ডিরেক্টরি ট্রিতে ফাইলের নাম উত্পন্ন করে। ডিরেক্টরি শীর্ষে গাছের প্রতিটি ডিরেক্টরিতে (শীর্ষে নিজেও এটি অন্তর্ভুক্ত), এটি একটি 3-টিপল (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
যেহেতু কিছু মন্তব্যকারীরা এটির জন্য টুইস্টেড লাইব্রেরিগুলি ব্যবহার করার সুবিধা কী তা জিজ্ঞাসা করেছেন, তাই আমি এখানে মূল প্রশ্নের বাইরে কিছুটা এগিয়ে যাব।
আছে কিছু উন্নত ডকুমেন্টেশন একটি শাখা যে FilePath সুবিধার ব্যাখ্যা হয়; আপনি এটি পড়তে চাইতে পারেন।
আরও নির্দিষ্টভাবে এই উদাহরণে: স্ট্যান্ডার্ড লাইব্রেরি সংস্করণ থেকে ভিন্ন, এই ফাংশনটি কোনও আমদানি ছাড়াই প্রয়োগ করা যেতে পারে । "সাবডিয়ার্স" ফাংশনটি সম্পূর্ণ জেনারিক, এতে এটি যুক্তি ব্যতীত অন্য কিছুতে কাজ করে না। স্ট্যান্ডার্ড লাইব্রেরি ব্যবহার করে ফাইলগুলি অনুলিপি করতে এবং সরানোর জন্য আপনাকে 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
objects দুর্ভাগ্যবশত ZipPath
এখনই কেবল পঠনযোগ্য, তবে এটি লেখার পক্ষে সমর্থন বাড়ানো যেতে পারে।
পরীক্ষার উদ্দেশ্যে আপনি নিজের জিনিসগুলিও পাস করতে পারেন। এখানে প্রস্তাবিত ওস.পাথ-ব্যবহার করে এপিআই পরীক্ষা করার জন্য, আপনাকে আমদানি করা নাম এবং অন্তর্নিহিত নির্ভরতা সহ বাঁদর করতে হবে এবং আপনার পরীক্ষাগুলি কাজে লাগানোর জন্য সাধারণত কালো যাদু করতে হয়। ফাইলপথ দিয়ে আপনি এমন কিছু করুন:
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')
আমাকে পথ.পি লাইব্রেরির উল্লেখ করতে হবে , যা আমি প্রায়শই ব্যবহার করি।
তাত্ক্ষণিক সাব-ডাইরেক্টরিগুলি আনার মতো সাধারণ হয়ে উঠুন:
my_dir.dirs()
পুরো কাজের উদাহরণটি হ'ল:
from path import Path
my_directory = Path("path/to/my/directory")
subdirs = my_directory.dirs()
এনবি: আমার_ডাইরেক্টরিটি এখনও স্ট্রিং হিসাবে ম্যানিপুলেট করা যায়, যেহেতু পাথ স্ট্রিংয়ের একটি সাবক্লাস, তবে পথগুলি পরিচালনা করার জন্য দরকারী পদ্ধতিগুলির একটি গুচ্ছ সরবরাহ করে
def get_folders_in_directories_recursively(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 (ডিরেক্টরি) -> সমস্ত উপ ফোল্ডার দেয়
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')
পাথলিব ব্যবহার করে একটি লাইনার:
list_subfolders_with_paths = [p for p in pathlib.Path(path).iterdir() if p.is_dir()]