現在のディレクトリ内のすべてのサブディレクトリのリストを取得する


560

Pythonの現在のディレクトリにあるすべてのサブディレクトリのリストを返す方法はありますか?

ファイルでこれを行うことができることはわかっていますが、代わりにディレクトリのリストを取得する必要があります。


回答:


604

直下のサブディレクトリ、またはツリーのすぐ下のすべてのディレクトリを意味しますか?

どちらの方法でも、os.walkこれを行うために使用できます。

os.walk(directory)

各サブディレクトリのタプルを生成します。3タプルの最初のエントリはディレクトリ名なので、

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

すべてのサブディレクトリが再帰的に表示されます。

タプルの2番目のエントリは、最初の位置にあるエントリの子ディレクトリのリストであるため、代わりにこれを使用することもできますが、あまり節約できない可能性があります。

ただし、直接の子ディレクトリを提供するためにのみ使用できます。

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

または、「Pythonで直接のサブディレクトリをすべて取得する方法」のソリューションを含め、os.listdirおよびを使用してすでに投稿されている他のソリューションを参照してください。os.path.isdir


7
os.walkはトリプル(ルート、ディレクトリ、ファイル)を返すと思います。つまり、dirsには多くの繰り返しエントリがあります。ディレクトリを再帰するより効率的な方法はありますか?
mathtick 2010

22
os.walk('.').next()[1]またはos.walk('.').__next__()[1]直接使用しないでください。代わりに、Python 2(ドキュメントを参照)Python 3(ドキュメントを参照)のnext()両方で利用可能な組み込み関数を使用してください。例:。next(os.walk('.'))[1]
Lucio Paiva、2015年

1
@Lucio os.walk('.').next()[1]直接使用するのはなぜ悪いのですか?
wisbucky

8
@wisbuckyはiteraror.__next__()内部メソッドであり、iterator.next()使用方法はnext()PEP-3114に従って組み込みに移行する必要があるため、これは悪い習慣です。参照PEP-3114 2007年に承認されました
ルシオパイヴァ

16
パフォーマンスの違いを懸念誰のためにos.walkos.listdir+ os.path.isdirソリューション:私は(下の階層内のファイル数百万の)万個のサブディレクトリとディレクトリ上でテストおよびパフォーマンスの違いはごくわずかです。os.walk:「10ループ、最高3:44.6ミリ秒/ループ」およびos.listdir+ os.path.isdir:「10ループ、最高3:45.1ミリ秒/ループ」
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
このアプローチでは、「。」で実行されない場合、abspath-issuesを処理する必要があることに注意してください。
daspostloch、

4
ヘッドアップだけです。cwd( '。')を使用していない場合は、os.path.joinオンにoしてフルパスを取得しない限り、これは機能しません。そうでない場合isdir(0)は、常にfalseを返します
James McMahon

5
上記の2つの問題の修正により、投稿が更新されたようです。
cgmb 2015年

1
呼び出しを避けるためにos.path.join二回、あなたが最初に参加してから使用してリストをフィルタリングすることができますos.path.isdirfilter(os.path.isdir, [os.path.join(d, o) for o in os.listdir(d)])
quant_dev

155

あなたはただ使うことができます glob.glob

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

末尾を忘れないでください/*


いいね。シンプル。ただ、/名前の末尾に
残る

9
あなたが想定することができない場合は/、フォルダの区切りであるためには、次の操作を行いますglob(os.path.join(path_to_directory, "*", ""))
juanmirocks

1
これはサブディレクトリでは機能しません!globを使用するには、これが完全な答えです:PythonでGlob()を使用してファイルを再帰的に検索しますか?
ポピー

1
グロブを再帰的にするには、次の引数を追加するだけですrecursive=True
JacoSolari

102

上記よりはるかに優れています。いくつかのos.path.join()が必要なく、フルパスを直接(必要に応じて)取得できるため、Python 3.5以降でこれを実行できます。

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

これにより、サブディレクトリへの完全なパスが提供されます。サブディレクトリの名前だけが必要な場合f.nameは、f.path

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


少しOT:すべてのサブフォルダーおよび/またはすべてのファイルを再帰的に必要とする場合は、この関数を見てください。これはos.walk&よりも高速でglob、すべてのサブフォルダーとそれらの(サブ)サブフォルダー内のすべてのファイルのリストを返します。 https://stackoverflow.com/a/59803793/2441026

すべてのサブフォルダーのみを再帰的に必要とする場合:

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

すべてのサブフォルダとそのフルパスのリストを返します。これもos.walkまた、よりも速く、はるかに高速ですglob


すべての機能の分析

tl; dr:
- フォルダのすべての直接のサブディレクトリを取得する場合は、を使用しますos.scandir
- すべてのサブディレクトリ(ネストされたものも含む)を取得する場合はos.walkfast_scandir上記の関数を使用するか、少し高速にしてください。
- os.walkトップレベルのサブディレクトリのみに使用しないでくださいos.scandir

  • 以下のコードを実行する場合は、必ず一度実行して、OSがフォルダーにアクセスし、結果を破棄してテストを実行してください。そうしないと、結果が台無しになります。
  • 関数呼び出しを混同したいと思うかもしれませんが、私はそれをテストしました、そしてそれは本当に問題ではありませんでした。
  • すべての例で、フォルダーへの完全パスが示されます。(Windows)Pathオブジェクトとしてのpathlibの例。
  • の最初の要素はos.walkベースフォルダになります。したがって、サブディレクトリしか取得できません。を使用fu.pop(0)して削除できます。
  • どの結果も自然ソートを使用しません。これは、結果が次のようにソートされることを意味します:1、10、2。自然なソート1、2、10)を取得するには、https://stackoverflow.com/a/48030307/2441026をご覧ください。


結果

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でテスト済み。

# -*- 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

サブディレクトリ内のすべてのサブディレクトリを検索する再帰的なソリューションが必要な場合は、以前に提案されたようにウォークを使用します。

現在のディレクトリの子ディレクトリだけが必要な場合はos.listdiros.path.isdir




19

os.listdir(path)を使用して、Python 2.7のサブディレクトリ(およびファイル)のリストを取得できます

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

59
これにはファイルも含まれます。
TarnayKálmán2014

2
「dir」はリストを形成するオブジェクトを指すのではなく、コンテナディレクトリを指すので、名前は紛らわしいです。あなたの1行の回答を確認してください。初心者のために、それらを選択するのは非常に魅力的です。
Titou

4
os.listdirファイルを含むディレクトリの内容をリストすることに注意してください。
guneysus

13

ディレクトリのみを一覧表示する

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)

現在のディレクトリ内のファイルのみを一覧表示する

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では機能しませんでした。問題は、os.listdirがディレクトリの名前のみを返し、フルパスを返さないことですが、os.path.isdirは、フルパスがディレクトリの場合にのみTrueを返すということだと思います。
デンソン2016年

これは、行をわずかに変更すると、現在のディレクトリの外部で機能します。subdirs = filter(os.path.isdir、[os.path.join(dir、x)for x in os.listdir(dir)])
RLC

12

Python 3.4は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のpathlib2モジュールを介し Python 2.7でも利用できます


ここでは、サブディレクトリのリストを反復処理するにはすてきな、きれいな構文は次のとおりです。for f in filter(Path.is_dir, p.iterdir()):
ブライアン・ローチ

11

Python 3.4とWindows UNCパスを使用してこの問題を見つけたので、この環境のバリアントを次に示します。

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の新機能であり、さまざまなOSでのパスの操作がはるかに簡単になります。https://docs.python.org/3.4/library/pathlib.html


10

この質問はずっと前に答え​​られましたが。を使用することをお勧めしますpathlibこれはWindowsおよびUnix OSで動作する堅牢な方法であるモジュールの。

したがって、サブディレクトリを含む特定のディレクトリのすべてのパスを取得するには:

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


9

ヒントをありがとう、みんな。私はソフトリンク(無限再帰)がdirsとして返されるという問題に遭遇しました。ソフトリンク?私たちは臭いのないソフトリンクを望んでいない!そう...

これにより、ソフトリンクではなく、dirsのみがレンダリングされました。

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

1
[x[0] for x in inf]それを調べることができるように、Pythonでは何と呼ばれていますか?
しんぞう2017

2
@shinzouそれはリストの理解です。超便利です。また、dictの理解度も調べます。
KurtB 2018

9

コピーフレンドリーipython

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

からの出力print(folders)

['folderA', 'folderB']

2
この場合のXは何ですか?
Abhishek Parikh 2018年

1
@AbhishekParikhはxによって作成されたリストから項目であるos.listdir(d)のでlistdir、彼が使用しているファイルとフォルダを返しますfilterとコマンドをos.path.isdirリストから任意のファイルをフィルタリングすることを。
James Burke

8

これが私のやり方です。

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

動作しません。xでは、isdir()を使用してチェックする完全なパスを提供する必要があると思います
niranjan patidar

おそらくos.getcwd();に問題があります。基本的には、絶対パスを取得して代わりに使用できます。dir = os.path.dirname(os.path.abspath(file))
Mujeeb Ishaque

os、pat.join()を使用するとうまくいきました。それはサブディレクトリの完全なパスを取得するのに役立ちましたので。
niranjan patidar

7

@Blair Conradの例に基づいた簡単な関数をいくつか示します-

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のソリューションに基づいて、次の例を使用します。

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"

どこ<your_directory>あなたがトラバースするディレクトリへのパスです。


5

フルパスとパスの説明付き ...\\..\\..\\subfolder、など:

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

4

この答えはまだ存在していないようです。

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

7
現在の作業ディレクトリ以外を検索している場合、これは常に空のリストを返します。これは、技術的にはOPが実行しようとしているものですが、あまり再利用できません。
ochawkeye 2017

2
ディレクトリ= [os.path.isdir(localDir + x)の場合、os.listdir(localDir)のxのx
Poonam

3

私は最近同様の質問をしました、そしてpython 3.6(ユーザーhavlockが追加された)の最良の答えはを使用することであることがわかりましたos.scandir。それを使った解決策はないようなので、自分で追加します。まず、ルートディレクトリの直下にあるサブディレクトリのみを一覧表示する非再帰的なソリューションです。

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

再帰バージョンは次のようになります。

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.pathサブディレクトリへの絶対パスを使用することに注意してください。フォルダ名だけが必要な場合は、entry.name代わりに使用できます。オブジェクトの詳細については、os.DirEntryを参照してくださいentry


実際、これが書かれている方法は3.5では機能せず、3.6でのみ機能します。あなたは、コンテキストマネージャを削除する必要が3.5上で使用するには-を参照してstackoverflow.com/questions/41401417/...
havlock

これは正しいです。3.5でコンテキストマネージャが実装されたことをどこかで読んだと断言できますが、それは間違っているようです。
アルベルトA

1

このようなものにフィルター関数os.path.isdirを使用しますos.listdir()filter(os.path.isdir,[os.path.join(os.path.abspath('PATH'),p) for p in os.listdir('PATH/')])


1

これにより、ファイルツリーのすぐ下にすべてのサブディレクトリが一覧表示されます。

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の新機能


1

指定されたファイルパス内のすべてのサブディレクトリのリストを返す関数。ファイルツリー全体を検索します。

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()を使用してすべてのフォルダーのリストを取得できます

import os

path = os.getcwd()

pathObject = os.walk(path)

このpathObjectはオブジェクトであり、次の方法で配列を取得できます

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

すべてのサブディレクトリのリストを取得するには、arrを繰り返し処理し、中央の配列を出力します

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

これにより、すべてのサブディレクトリが印刷されます。

すべてのファイルを取得するには:

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

0

この関数は、指定された親を使用directoryして、そのすべての関数をdirectories再帰的に繰り返し、内部で見つかったprintsすべての関数を繰り返しfilenamesます。あまりにも便利です。

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

ここから複数のソリューションに参加することで、これは私が最終的に使用したものです:

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, '*')))]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.