Geçerli dizindeki tüm alt dizinlerin listesini alma


Yanıtlar:


602

Anında alt dizinler mi yoksa ağaç altındaki her dizin mi demek istediniz?

Her iki durumda da, bunu os.walkyapmak için kullanabilirsiniz :

os.walk(directory)

her alt dizin için bir demet verir. 3 parçasındaki ilk girdi bir dizin adıdır, yani

[x[0] for x in os.walk(directory)]

size tüm alt dizinleri yinelemeli olarak vermelidir.

Gruptaki ikinci girişin, birinci konumdaki girişin alt dizinlerinin listesi olduğunu unutmayın, bunun yerine bunu kullanabilirsiniz, ancak sizi çok fazla kurtaramaz.

Ancak, bunu size hemen alt dizinleri vermek için kullanabilirsiniz:

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

Veya diğer çözümler zaten yayınlanmıştır kullanarak bkz os.listdirve os.path.isdir"nde olanlar dahil, nasıl Python hemen alt dizinleri tüm almak için ".


7
Bence os.walk üçlüyü (root, dirs, dosyalar) döndürüyor. Bu dirs yinelenen birçok girişi olduğu anlamına gelir. Dizinler aracılığıyla geri çekmenin daha etkili bir yolu var mı?
mathtick

22
Doğrudan os.walk('.').next()[1]veya os.walk('.').__next__()[1]doğrudan kullanmayın . Bunun yerine, next()hem Python 2'de (bkz. Doc) hem de Python 3'te (bkz. Doc) bulunan yerleşik işlevi kullanın . Örneğin: next(os.walk('.'))[1].
Lucio Paiva

1
@Lucio os.walk('.').next()[1]Doğrudan kullanmak neden kötü ?
wisbucky

8
@wisbucky bu kötü bir uygulamadır, çünkü iteraror.__next__()dahili bir yöntemdir ve iterator.next()kullanım next()PEP-3114'e göre yerleşik olana geçirilmelidir. 2007'de onaylanan PEP-3114'e bakınız .
Lucio Paiva

16
os.walkVe os.listdir+ os.path.isdirçözümleri arasındaki performans farkları hakkında endişe duyan herkes için : 10.000 alt dizin içeren bir dizinde test ettim (aşağıdaki hiyerarşide milyonlarca dosya var) ve performans farkları göz ardı edilebilir. os.walk: "10 döngü, döngü başına 3: 44,6 milisaniyenin en iyisi" ve os.listdir+ os.path.isdir: "döngü başına 3 döngü: 45,1 milisaniyenin en iyisi"
kevinmicke

165
import os

d = '.'
[os.path.join(d, o) for o in os.listdir(d) 
                    if os.path.isdir(os.path.join(d,o))]

5
Bu yaklaşımda, '.' ile yürütülmezse abspath konularına dikkat etmeniz gerektiğini unutmayın.
daspostloch

4
Eğer ( '') cwd kullanmıyorsanız bir yapmadıkça sadece kafaları yukarı, bu işe yaramaz os.path.joinüzerinde otam yolunu almak için aksi takdirde isdir(0)her zaman false döndürür
James McMahon

5
Gönderinin, yukarıda belirtilen iki sorun için düzeltmelerle güncellendiği anlaşılıyor.
cgmb

1
Çağıran önlemek için os.path.joiniki kez, önce katılmak ve daha sonra kullanarak listeyi filtreleyebilirsiniz os.path.isdir: filter(os.path.isdir, [os.path.join(d, o) for o in os.listdir(d)])
quant_dev

155

Sadece kullanabilirsin glob.glob

from glob import glob
glob("/path/to/directory/*/")

/Sonra izleyen unutmayın *.


Güzel. Basit. Sadece, /isimlerin
sonundaki izleri

9
Eğer kabul edemeyiz Eğer /klasör ayırıcı olmak gerekirse, bu yapın:glob(os.path.join(path_to_directory, "*", ""))
juanmirocks

1
Bu alt dizinler için geçerli değildir! Glob'u kullanmak için tam yanıt: Python'da dosyaları özyineli olarak bulmak için bir Glob () kullanın?
poppie

1
glob özyinelemek için aşağıdaki argümanı ekleyebilirsinizrecursive=True
JacoSolari

102

Yukarıdakilerden çok daha güzel, çünkü birkaç os.path.join () öğesine ihtiyacınız yoktur ve tam yolu doğrudan alırsınız (isterseniz), bunu Python 3.5 ve üzeri ile yapabilirsiniz.

subfolders = [ f.path for f in os.scandir(folder) if f.is_dir() ]

Bu, alt dizinin tam yolunu verecektir. Yalnızca alt dizinin adını kullanmak f.nameyerinef.path

https://docs.python.org/3/library/os.html#os.scandir


Biraz OT: Eğer ihtiyaç ardışık tüm alt klasör ve / veya ardışık tüm dosyalar , daha hızlı olan bu işlev bir göz var os.walkve globve iyi olanlar (alt) alt klasörler içindeki tüm dosyaları gibi tüm alt klasörlerin bir listesini döndürür: https://stackoverflow.com/a/59803793/2441026

Yalnızca tüm alt klasörleri yinelemeli olarak istiyorsanız :

def fast_scandir(dirname):
    subfolders= [f.path for f in os.scandir(dirname) if f.is_dir()]
    for dirname in list(subfolders):
        subfolders.extend(fast_scandir(dirname))
    return subfolders

Tüm alt klasörlerin tam yollarını içeren bir listesini döndürür. Bu yine daha hızlı os.walkve çok daha hızlı glob.


Tüm fonksiyonların analizi

tl; dr:
- Bir klasör kullanımı için hemen tüm alt dizinleri almak istiyorsanız os.scandir.
- Tüm alt dizinleri, hatta iç içe geçmiş olanları almak istiyorsanız , yukarıdaki işlevi os.walkveya - biraz daha hızlı kullanın fast_scandir.
- Asla os.walksadece üst düzey alt dizinler için kullanmayın , çünkü yüzlerce (!) Kat daha yavaş olabilir os.scandir.

  • Aşağıdaki kodu çalıştırırsanız, işletim sisteminizin klasöre erişebilmesi için bir kez çalıştırdığınızdan emin olun, sonuçları atın ve testi çalıştırın, aksi takdirde sonuçlar berbat olacaktır.
  • İşlev çağrılarını karıştırmak isteyebilirsiniz, ancak test ettim ve gerçekten önemli değildi.
  • Tüm örnekler klasörün tam yolunu verecektir. (Windows) Yol nesnesi olarak pathlib örneği.
  • Öğesinin ilk öğesi os.walktemel klasör olacaktır. Yani sadece alt dizinleri almayacaksınız. fu.pop(0)Kaldırmak için kullanabilirsiniz .
  • Sonuçların hiçbiri doğal sıralama kullanmaz . Bu, sonuçların şu şekilde sıralanacağı anlamına gelir: 1, 10, 2. Doğal sıralama (1, 2, 10) elde etmek için lütfen https://stackoverflow.com/a/48030307/2441026 adresine bakın.


Sonuçlar :

os.scandir      took   1 ms. Found dirs: 439
os.walk         took 463 ms. Found dirs: 441 -> it found the nested one + base folder.
glob.glob       took  20 ms. Found dirs: 439
pathlib.iterdir took  18 ms. Found dirs: 439
os.listdir      took  18 ms. Found dirs: 439

W7x64, Python 3.8.1 ile test edilmiştir.

# -*- coding: utf-8 -*-
# Python 3


import time
import os
from glob import glob
from pathlib import Path


directory = r"<insert_folder>"
RUNS = 1


def run_os_walk():
    a = time.time_ns()
    for i in range(RUNS):
        fu = [x[0] for x in os.walk(directory)]
    print(f"os.walk\t\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")


def run_glob():
    a = time.time_ns()
    for i in range(RUNS):
        fu = glob(directory + "/*/")
    print(f"glob.glob\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")


def run_pathlib_iterdir():
    a = time.time_ns()
    for i in range(RUNS):
        dirname = Path(directory)
        fu = [f for f in dirname.iterdir() if f.is_dir()]
    print(f"pathlib.iterdir\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")


def run_os_listdir():
    a = time.time_ns()
    for i in range(RUNS):
        dirname = Path(directory)
        fu = [os.path.join(directory, o) for o in os.listdir(directory) if os.path.isdir(os.path.join(directory, o))]
    print(f"os.listdir\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")


def run_os_scandir():
    a = time.time_ns()
    for i in range(RUNS):
        fu = [f.path for f in os.scandir(directory) if f.is_dir()]
    print(f"os.scandir\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms.\tFound dirs: {len(fu)}")


if __name__ == '__main__':
    run_os_scandir()
    run_os_walk()
    run_glob()
    run_pathlib_iterdir()
    run_os_listdir()

35

Alt dizinlerdeki tüm alt dizinleri bulan özyinelemeli bir çözüme ihtiyacınız varsa, daha önce önerildiği gibi walk komutunu kullanın.

Yalnızca geçerli dizinin alt dizinlerine ihtiyacınız varsa os.listdir,os.path.isdir




19

Python 2.7 içindeki alt dizinlerin (ve dosyaların) listesini os.listdir (yol) kullanarak alabilirsiniz

import os
os.listdir(path)  # list of subdirectories and files

59
Buna dosyalar da dahildir.
Tarnay Kálmán

2
'Dir', listeyi oluşturan nesnelere değil, konteyner dizinine atıfta bulunduğundan, kafa karıştırıcıdır. Lütfen tek satırlık cevaplarınızı kontrol edin, yeni başlayanlar için onları seçmek çok caziptir.
Titou

4
os.listdirDosyaların dahil olduğu dizinin içeriğini listelediğine dikkat edin .
guneysus

13

Yalnızca dizinleri listeleme

print("\nWe are listing out only the directories in current directory -")
directories_in_curdir = filter(os.path.isdir, os.listdir(os.curdir))
print(directories_in_curdir)

Yalnızca geçerli dizindeki dosyaları listeleme

files = filter(os.path.isfile, os.listdir(os.curdir))
print("\nThe following are the list of all files in the current directory -")
print(files)

2
Mac OS'de çalışmadı. Sorun os.listdir tam dizini değil, sadece dizinin adını döndürmek olduğunu düşünüyorum ama os.path.isdir tam yolu bir dizinse yalnızca True döndürür.
denson

Satırı biraz değiştirirseniz, bu geçerli dizinin dışında çalışır: subdirs = filter (os.listdir (dir)] içindeki x için os.path.isdir, [os.path.join (dir, x)
RLC

12

Piton 3.4 kişiye modülü kolu dosya sistemi yolları için bir nesne yönelimli yaklaşım sağlar standart kitaplığı, içine:pathlib

from pathlib import Path

p = Path('./')

# List comprehension
[f for f in p.iterdir() if f.is_dir()]

# The trailing slash to glob indicated directories
# This will also include the current directory '.'
list(p.glob('**/'))

Pathlib, PyPi'deki pathlib2 modülü aracılığıyla Python 2.7'de de mevcuttur .


Alt dizinler listesini yinelemek için, güzel, temiz bir sözdizimi:for f in filter(Path.is_dir, p.iterdir()):
Bryan Roach

11

Python 3.4 ve Windows UNC yollarını kullanarak bu soruna tökezlediğim için, bu ortamın bir varyantı:

from pathlib import WindowsPath

def SubDirPath (d):
    return [f for f in d.iterdir() if f.is_dir()]

subdirs = SubDirPath(WindowsPath(r'\\file01.acme.local\home$'))
print(subdirs)

Pathlib, Python 3.4'te yenidir ve farklı işletim sistemleri altındaki yollarla çalışmayı çok daha kolay hale getirir: https://docs.python.org/3.4/library/pathlib.html


10

Bu soru uzun zaman önce cevaplanmış olmasına rağmen. pathlibModülü Windows ve Unix OS üzerinde çalışmanın güçlü bir yolu olduğu için kullanmanızı tavsiye ederim .

Dolayısıyla, alt dizinler dahil belirli bir dizindeki tüm yolları almak için:

from pathlib import Path
paths = list(Path('myhomefolder', 'folder').glob('**/*.txt'))

# all sorts of operations
file = paths[0]
file.name
file.stem
file.parent
file.suffix

vb.


9

İpuçları için teşekkürler çocuklar. Ben dirs olarak dönen softlink (sonsuz özyineleme) ile ilgili bir sorunla karşılaştı. Sembolik bağlantıları? Sızdırmaz yumuşak bağlantı istemiyoruz! Yani...

Bu sadece dirsekleri oluşturdu, yumuşak bağlantıları değil:

>>> import os
>>> inf = os.walk('.')
>>> [x[0] for x in inf]
['.', './iamadir']

1
[x[0] for x in inf]Bakabilmek için python'da ne denir?
shinzou

2
@shinzou Bu bir liste kavraması. Süper kullanışlı. Ayrıca diksiyon kavrayışlarına bakınız.
KurtB

9

Kopyalama yapıştırma dostu ipython:

import os
d='.'
folders = list(filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d)))

Çıktı kaynağı print(folders):

['folderA', 'folderB']

2
Bu durumda X nedir?
Abhishek Parikh

1
@AbhishekParikh xtarafından oluşturulan listeden bir öğedir, os.listdir(d)çünkü listeden herhangi bir dosyayı filtrelemek listdiriçin filterkomutunu kullandığı dosya ve klasörleri döndürür os.path.isdir.
James Burke

8

Ben böyle yaparım.

    import os
    for x in os.listdir(os.getcwd()):
        if os.path.isdir(x):
            print(x)

İşe yaramıyor. Sanırım x içinde isdir () kullanarak kontrol etmek için tam bir yol sağlamak zorunda
niranjan patidar

Muhtemelen os.getcwd () ile ilgili sorun yaşıyorsunuz; Esasen, yapabileceğiniz şey mutlak yolu elde etmek ve bunun yerine kullanmaktır. dir = os.path.dirname (os.path.abspath ( dosya ))
Mujeeb Ishaque

os kullanarak, pat.join () benim için çalıştı. Çünkü alt dizinin tam yolunu bulmaya yardımcı oldu.
niranjan patidar

7

@Blair Conrad'ın örneğine dayanan birkaç basit fonksiyon:

import os

def get_subdirs(dir):
    "Get a list of immediate subdirectories"
    return next(os.walk(dir))[1]

def get_subfiles(dir):
    "Get a list of immediate subfiles"
    return next(os.walk(dir))[2]

6

Eli Bendersky'nin çözümünü temel alarak aşağıdaki örneği kullanın:

import os
test_directory = <your_directory>
for child in os.listdir(test_directory):
    test_path = os.path.join(test_directory, child)
    if os.path.isdir(test_path):
        print test_path
        # Do stuff to the directory "test_path"

nerede <your_directory> gitmek istediğiniz dizinin yolu.


5

Tam yol ve yol varlık muhasebesi ile ., .., \\, ..\\..\\subfolder, vb:

import os, pprint
pprint.pprint([os.path.join(os.path.abspath(path), x[0]) \
    for x in os.walk(os.path.abspath(path))])

4

Bu cevap zaten mevcut değildi.

directories = [ x for x in os.listdir('.') if os.path.isdir(x) ]

7
Geçerli çalışma dizininden başka bir şey arıyorsanız, bu OP'nin teknik olarak yapmak istediği şeydir, ancak çok yeniden kullanılamazsa, bu her zaman boş bir liste döndürür.
ochawkeye

2
dizinler = os.path.isdir (localDir + x) ise os.listdir (localDir) içindeki x için x
Poonam

3

Son zamanlarda benzer bir soru yaşadım ve python 3.6 (kullanıcı havlock eklendi gibi) için en iyi cevap kullanmak olduğunu öğrendim os.scandir. Kullanan bir çözüm olmadığı için kendim ekleyeceğim. İlk olarak, doğrudan kök dizinin altındaki alt dizinleri listeleyen özyinelemeli olmayan bir çözüm.

def get_dirlist(rootdir):

    dirlist = []

    with os.scandir(rootdir) as rit:
        for entry in rit:
            if not entry.name.startswith('.') and entry.is_dir():
                dirlist.append(entry.path)

    dirlist.sort() # Optional, in case you want sorted directory names
    return dirlist

Özyinelemeli sürüm şöyle görünecektir:

def get_dirlist(rootdir):

    dirlist = []

    with os.scandir(rootdir) as rit:
        for entry in rit:
            if not entry.name.startswith('.') and entry.is_dir():
                dirlist.append(entry.path)
                dirlist += get_dirlist(entry.path)

    dirlist.sort() # Optional, in case you want sorted directory names
    return dirlist

entry.pathalt dizine giden mutlak yolu kullanan unutmayın . Yalnızca klasör adına ihtiyacınız varsa kullanabilirsiniz entry.name. Nesne hakkında ek ayrıntılar için os.DirEntry dosyasına bakın entry.


Aslında, bunun yazılma şekli 3.5 üzerinde çalışmayacak, sadece 3.6. 3.5
sürümünde

Doğru. İçerik yöneticisinin 3.5'te uygulandığını bir yerde okuduğuma yemin edebilirim, ama yanılmışım gibi görünüyor.
Alberto A

1

böyle bir şey os.path.isdirüzerinde bir filtre işlevi kullanos.listdir()filter(os.path.isdir,[os.path.join(os.path.abspath('PATH'),p) for p in os.listdir('PATH/')])


1

Bu, tüm alt dizinleri dosya ağacının hemen altında listeler.

import pathlib


def list_dir(dir):
    path = pathlib.Path(dir)
    dir = []
    try:
        for item in path.iterdir():
            if item.is_dir():
                dir.append(item)
                dir = dir + list_dir(item)
        return dir
    except FileNotFoundError:
        print('Invalid directory')

pathlib 3.4 sürümünde yeni


1

Belirli bir dosya yolu içindeki tüm alt dizinlerin listesini döndürme işlevi. Tüm dosya ağacında arama yapar.

import os

def get_sub_directory_paths(start_directory, sub_directories):
    """
    This method iterates through all subdirectory paths of a given 
    directory to collect all directory paths.

    :param start_directory: The starting directory path.
    :param sub_directories: A List that all subdirectory paths will be 
        stored to.
    :return: A List of all sub-directory paths.
    """

    for item in os.listdir(start_directory):
        full_path = os.path.join(start_directory, item)

        if os.path.isdir(full_path):
            sub_directories.append(full_path)

            # Recursive call to search through all subdirectories.
            get_sub_directory_paths(full_path, sub_directories)

return sub_directories

1

os.walk () kullanarak tüm klasörlerin listesini alabiliriz

import os

path = os.getcwd()

pathObject = os.walk(path)

Bu pathObject bir nesnedir ve bir dizi

arr = [x for x in pathObject]

arr is of type [('current directory', [array of folder in current directory], [files in current directory]),('subdirectory', [array of folder in subdirectory], [files in subdirectory]) ....]

Tüm alt dizinlerin listesini arr üzerinden yineleyerek ve orta diziyi yazdırarak alabiliriz

for i in arr:
   for j in i[1]:
      print(j)

Bu, tüm alt dizini basacaktır.

Tüm dosyaları almak için:

for i in arr:
   for j in i[2]:
      print(i[0] + "/" + j)

0

Bu işlev, belirli bir üst directoryöğeyle birlikte tüm directoriesözyinelemeleri ve içinde bulduğu printsher şeyi yineler filenames. Çok faydalı.

import os

def printDirectoryFiles(directory):
   for filename in os.listdir(directory):  
        full_path=os.path.join(directory, filename)
        if not os.path.isdir(full_path): 
            print( full_path + "\n")


def checkFolders(directory):

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

    #print(dir_list)

    for dir in dir_list:           
        print(dir)
        checkFolders(directory +"/"+ dir) 

    printDirectoryFiles(directory)       

main_dir="C:/Users/S0082448/Desktop/carpeta1"

checkFolders(main_dir)


input("Press enter to exit ;")

0

Buradan birden fazla çözüme katılarak, bunu kullanarak sonuçlandırdım:

import os
import glob

def list_dirs(path):
    return [os.path.basename(x) for x in filter(
        os.path.isdir, glob.glob(os.path.join(path, '*')))]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.