पायथन में सभी तत्काल उपनिर्देशिका कैसे प्राप्त करें


150

मैं एक साधारण पायथन स्क्रिप्ट लिखने की कोशिश कर रहा हूं जो सब (सब अपवादों के साथ) सब उपनिर्देशिकाओं में एक index.tpl को index.html पर कॉपी करेगा।

मैं उपनिर्देशिकाओं की सूची प्राप्त करने की कोशिश कर रहा हूँ।


11
आपको लग सकता है कि इस पहले दिए गए उत्तर पर एसओ प्रश्न हल करता है: stackoverflow.com/questions/120656/directory-listing-in-python
जरेट हार्डी

जवाबों:


31

मैंने सभी मौजूदा उपनिर्देशिकाओं के लिए पूर्ण पथ को वापस करने के लिए विभिन्न कार्यों पर कुछ गति परीक्षण किया ।

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, 32x से तेज listdir(फिल्टर से), 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

W7x64, पायथन 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}")

1
बस आपको धन्यवाद देना चाहता हूं, वास्तव में इस की तलाश थी। महान विश्लेषण।
Cing

225
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))]

76

किसी ने उल्लेख क्यों नहीं किया glob? globआपको यूनिक्स-शैली पाथनेम विस्तार का उपयोग करने की अनुमति देता है, और मेरी लगभग सभी चीजों के लिए काम करने वाला है जो एक से अधिक पथ नाम खोजने की आवश्यकता है। यह बहुत आसान बनाता है:

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

नोट करें कि globअंतिम स्लैश के साथ निर्देशिका वापस आ जाएगी (यूनिक्स के रूप में) जबकि अधिकांश pathआधारित समाधान अंतिम स्लैश को छोड़ देंगे।


3
अच्छा समाधान, सरल और काम करता है। जो लोग उस अंतिम स्लैश को नहीं चाहते हैं, वह इसका उपयोग कर सकते हैं paths = [ p.replace('/', '') for p in glob('*/') ]
इवान हू

5
हो सकता है कि यह केवल अंतिम चरित्र को ही काट दे [p[:-1] for p in paths], क्योंकि प्रतिस्थापित विधि फ़ाइल नाम में किसी भी बची हुई आगे की स्लैश को बदल देगी (ऐसा नहीं है कि वे आम हैं)।
अरी

3
यहां तक ​​कि सुरक्षित, अनुगामी स्लैश को हटाने के लिए पट्टी ('/') का उपयोग करें। इस तरह गारंटी देता है कि आप किसी भी ऐसे पात्र को नहीं काटते हैं जो आगे की स्लैश नहीं हैं
एलीइज़र मिरॉन

8
निर्माण से आपको एक अनुगामी स्लेश की गारंटी है (इसलिए यह सुरक्षित नहीं है), लेकिन मुझे लगता है कि यह अधिक पठनीय है। आप निश्चित रूप से rstripइसके बजाय उपयोग करना चाहते हैं strip, हालांकि, उत्तरार्द्ध किसी भी पूरी तरह से योग्य पथ को सापेक्ष पथ में बदल देगा।
अरी जुएल

7
अजगर न्यूबीज़ के लिए @ारी टिप्पणी के पूरक जैसे मैं: strip('/')शुरू करने वाले और पीछे आने वाले दोनों को हटा दूंगा / '', rstrip('/')केवल पीछे वाले को हटा देगा
टिटौ

35

" वर्तमान निर्देशिका में सभी उपनिर्देशिकाओं की सूची प्राप्त करना " जांचें ।

यहाँ एक पायथन 3 संस्करण है:

import os

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

print(dir_list)

2
अत्यंत चतुर। जबकि दक्षता मायने नहीं रखती ( ... यह पूरी तरह से करता है ), मैं इस बात से उत्सुक हूं कि क्या यह या ग्लोब आधारित जनरेटर अभिव्यक्ति (s.rstrip("/") for s in glob(parent_dir+"*/"))अधिक समय कुशल है। मेरा सहज संदेह यह है कि एक- stat()आधारित os.walk()समाधान शैल-शैली के ग्लोबिंग की तुलना में गहरा होना चाहिए। दुख की बात है कि मेरे पास इच्छाशक्ति की कमी है timeitऔर वास्तव में मुझे इसका पता है।
सेसिल करी

3
ध्यान दें कि यह पूर्वनिर्धारित निर्देशिका नाम के बिना उपनिर्देशिका नाम लौटाता है।
पॉल चेरोच

19
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(...) )
user136036

12

os.walk इस स्थिति में आपका दोस्त है।

प्रलेखन से सीधे:

वॉक () एक डायरेक्टरी ट्री में फ़ाइल नाम जेनरेट करता है, वॉक करके ट्री या तो ऊपर या नीचे से ऊपर जाता है। निर्देशिका शीर्ष पर निहित पेड़ में प्रत्येक निर्देशिका के लिए (शीर्ष स्वयं सहित), यह एक 3-टपल (dirpath, dirnames, फ़ाइल नाम) देता है।


1
बस इस बात का ध्यान रखें कि यदि आप केवल प्रथम-स्तरीय उपनिर्देशिकाएँ चाहते हैं, तो वापसी मानों के पहले सेट के बाद os.walk पुनरावृत्ति से बाहर निकलें।
योयो

11

यह विधि अच्छी तरह से यह सब एक बार में करता है।

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

7

Twisted के FilePath मॉड्यूल का उपयोग करना:

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वस्तुओं के बीच । दुर्भाग्य से ZipPathअभी-अभी पढ़ा गया है, लेकिन इसे लेखन के समर्थन में बढ़ाया जा सकता है।

आप परीक्षण उद्देश्यों के लिए अपनी खुद की वस्तुओं को भी पास कर सकते हैं। यहाँ सुझाए गए os.path- उपयोग करने वाले API का परीक्षण करने के लिए, आपको आयात किए गए नामों और निहित निर्भरताओं के साथ बंदर करना होगा और आम तौर पर अपने परीक्षणों को काम करने के लिए काला जादू करना होगा। FilePath के साथ, आप कुछ इस तरह से करते हैं:

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(...))

चूंकि मेरे पास ट्विस्टेड के लिए बहुत कम जोखिम है, इसलिए मैं हमेशा अतिरिक्त जानकारी और उदाहरणों का स्वागत करता हूं; यह उत्तर उसके लिए देखना अच्छा है। कहा जाता है कि, चूंकि यह दृष्टिकोण बिल्ट-इन अजगर मॉड्यूल, और ट्विस्टेड इंस्टाल का उपयोग करने की तुलना में बहुत अधिक काम करने की आवश्यकता प्रतीत होता है, तो क्या इसका उपयोग करने के कोई फायदे हैं जो आप उत्तर में जोड़ सकते हैं?
जरेट हार्डी

1
ग्लिफ़ का उत्तर संभवतः इस तथ्य से प्रेरित था कि ट्विस्टेडलोर .tpl फ़ाइलों का भी उपयोग करता है।
कांस्टेंटिन

ठीक है, स्पष्ट रूप से मैं स्पैनिश जिज्ञासा की उम्मीद नहीं करता हूं :-) मैंने "* .tpl" को कुछ सार विस्तार अर्थ "टेम्पलेट" के लिए एक सामान्य संदर्भ माना था, न कि एक विशिष्ट मुड़ टेम्पलेट (मैंने देखा है। यह कई में उपयोग किया जाता है।) सभी भाषाओं के बाद)। जानकार अच्छा लगा।
जरेट हार्डी

+1 इसलिए संभव ट्विस्टेड एंगल की ओर मुड़ने के लिए, हालांकि मैं अभी भी समझना चाहूंगा कि ट्विस्टेड फाइलपथ 'ऑब्जेक्ट' और 'वॉक' (')' फंक्शन 'को मानक एपीआई में जोड़ता है।
जरेट हार्डी

व्यक्तिगत रूप से मुझे लगता है कि "FilePath.walk () पैदावार वस्तुओं को याद रखने में बहुत आसान है" os.walk पैदावार dir, dirs, फ़ाइलों की तुलना में 3-tuples। लेकिन इसके और भी फायदे हैं। FilePath बहुरूपता के लिए अनुमति देता है, जिसका अर्थ है कि आप फाइलसिस्टम के अलावा अन्य चीजों को पार कर सकते हैं। उदाहरण के लिए, आप मेरे 'सबडिरर्स' फंक्शन में एक twisted.python.zippath.ZipArchive पास कर सकते हैं और FilePaths के बजाय ZipPaths का एक जनरेटर प्राप्त कर सकते हैं; आपका तर्क नहीं बदलता है, लेकिन आपका आवेदन अब जादुई रूप से ज़िप फाइलों को संभालता है। यदि आप इसका परीक्षण करना चाहते हैं, तो आपको बस एक वस्तु की आपूर्ति करनी है, आपको वास्तविक फाइलें नहीं लिखनी हैं।
ग्लिफ़

4

मैंने सिर्फ vmware वर्चुअल मशीन को स्थानांतरित करने के लिए कुछ कोड लिखे, और उप-निर्देशिकाओं के बीच फाइल कॉपी को पूरा करने 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))

यह बहुत सुरुचिपूर्ण नहीं है, लेकिन यह काम करता है।


1

यहाँ एक तरीका है:

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')

-1: काम नहीं करेगा, क्योंकि shutil.copy वर्तमान dir पर कॉपी होगी, इसलिए आप उपनिर्देशिका ट्री में मिलने वाले प्रत्येक 'index.tpl' के लिए एक बार वर्तमान dir में 'index.html' को ओवरराइट कर देंगे।
nosklo

1

मुझे path.py का उल्लेख करना है लाइब्रेरी , जिसका मैं बहुत बार उपयोग करता हूं।

तत्काल उपनिर्देशिका प्राप्त करना उतना ही सरल हो जाता है:

my_dir.dirs()

पूर्ण कार्य उदाहरण है:

from path import Path

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

subdirs = my_directory.dirs()

NB: my_directory अभी भी एक स्ट्रिंग के रूप में हेरफेर किया जा सकता है, क्योंकि पथ स्ट्रिंग का एक उपवर्ग है, लेकिन पथों में हेरफेर करने के लिए उपयोगी तरीकों का एक गुच्छा प्रदान करता है।


1
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 (निर्देशिका) -> सभी उप फ़ोल्डर देता है


अच्छा कर रहा है, संस्करण अजगर 3.6, लेकिन मुझे "सेल्फ" को मिटाने की जरूरत है, फंक्शन वेरिएबल्स के अंदर से
लोकोमोटिव

1
एक वर्ग के अंदर उपयोग कर रहा था, अपडेट किया है
कनिष मैथ्यू

0
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']

0
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')

0

Pathlib का उपयोग कर एक लाइनर:

list_subfolders_with_paths = [p for p in pathlib.Path(path).iterdir() if p.is_dir()]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.