Pythonの最上位ディレクトリのみを一覧表示する方法は?


132

一部のフォルダ内のディレクトリのみを一覧表示できるようにしたい。これは、ファイル名を一覧表示したくない、または追加のサブフォルダを必要としないことを意味します。

例が役立つかどうか見てみましょう。現在のディレクトリには次のものがあります。

>>> os.listdir(os.getcwd())
['cx_Oracle-doc', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'LICENSE.txt', 'mod_p
ython-wininst.log', 'NEWS.txt', 'pymssql-wininst.log', 'python.exe', 'pythonw.ex
e', 'README.txt', 'Removemod_python.exe', 'Removepymssql.exe', 'Scripts', 'tcl',
 'Tools', 'w9xpopen.exe']

ただし、ファイル名をリストに含めたくありません。\ Lib \ cursesなどのサブフォルダーも必要ありません。基本的に私が欲しいものは以下で動作します:

>>> for root, dirnames, filenames in os.walk('.'):
...     print dirnames
...     break
...
['cx_Oracle-doc', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'Scripts', 'tcl', 'Tools']

しかし、私は同じ結果を達成するためのより簡単な方法があるのだろうかと思っています。トップレベルに戻るためだけにos.walkを使用するのは、非効率的/多すぎるという印象を受けます。

回答:


125

os.path.isdir()を使用して結果をフィルタリングします(実際のパスを取得するにはos.path.join()を使用します):

>>> [ name for name in os.listdir(thedir) if os.path.isdir(os.path.join(thedir, name)) ]
['ctypes', 'distutils', 'encodings', 'lib-tk', 'config', 'idlelib', 'xml', 'bsddb', 'hotshot', 'logging', 'doc', 'test', 'compiler', 'curses', 'site-packages', 'email', 'sqlite3', 'lib-dynload', 'wsgiref', 'plat-linux2', 'plat-mac']

17
これには非常に単純なos.walk()。next()[1]と比較して多くの処理が必要です
Phyo Arkar Lwin 2012

202

os.walk

使用os.walkしてnextアイテム機能:

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

のPython <= 2.5の使用:

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

この仕組み

os.walkジェネレーターであり、呼び出しnextは3タプル(dirpath、dirnames、filenames)の形式で最初の結果を取得します。したがって、[1]インデックスはdirnamesそのタプルからののみを返します。


14
これについてもう少し説明すると、これはジェネレーターであり、指示がない限り他のディレクトリを歩くことはありません。したがって、.next()[1]は、すべてのリスト内包表記が行うことを1行で実行します。私はおそらくのような何かをしたいDIRNAMES=1、その後、next()[DIRNAMES]それが簡単に将来のコードのメンテナのために理解できるようにすること。
ボートコーダー

3
+1素晴らしいソリューション。、閲覧に使用するディレクトリを指定するには:os.walk( os.path.join(mypath,'.')).next()[1]
ダニエル・レイス

42
Python v3の場合:next(os.walk( '。'))[1]
Andre Soares

あなたがテキスト処理以上のものをするつもりなら; すなわち、実際のフォルダの完全なパスの処理が必要になる可能性があります:sorted( [os.path.join(os.getcwd(), item) for item in os.walk(os.curdir).next()[1]] )
DevPlayer

52

os.path.isdirを使用してリストをフィルタリングし、ディレクトリを検出します。

filter(os.path.isdir, os.listdir(os.getcwd()))

5
これは、これらの答えのいずれにおいても、読みやすさと簡潔さの最良の組み合わせであると思います。
vergenzt 2012

20
これはうまくいきませんでした。私の推測ではos.listdir、に渡されたファイル/フォルダ名が返されますos.path.isdirが、後者には完全パスが必要です。
Daniel Reis

3
フィルターはos.walkより高速です timeit(os.walk(os.getcwd()).next()[1]) 1000 loops, best of 3: 734 µs per loop timeit(filter(os.path.isdir, os.listdir(os.getcwd()))) 1000 loops, best of 3: 477 µs per loop
B.Kocis

14
directories=[d for d in os.listdir(os.getcwd()) if os.path.isdir(d)]

4
これは、フィルタ(os.path.isdir、os.listdir(os.getcwd())に短縮することができる
ジョン・ミリキン

3
誰かがフィルタまたはリスト内包がより速いかどうかについて何か情報がありますか?そうでなければ、それは主観的な議論です。もちろん、これはcwdに1000万のディレクトリがあり、パフォーマンスが問題であることを前提としています。
マークロディ

12

を行う代わりにos.listdir(os.getcwd())os.listdir(os.path.curdir)。関数呼び出しが1つ少なくなり、移植性も高くなります。

したがって、答えを完成させるには、フォルダ内のディレクトリのリストを取得します。

def listdirs(folder):
    return [d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d))]

完全パス名を使用する場合は、次の関数を使用してください:

def listdirs(folder):
    return [
        d for d in (os.path.join(folder, d1) for d1 in os.listdir(folder))
        if os.path.isdir(d)
    ]

9

これも動作するようです(少なくともLinuxでは):

import glob, os
glob.glob('*' + os.path.sep)

1
の+1 glob。多くのコード、特に反復を節約でき、UNIX端末の使用法(ls)に非常に似ています
Gerard

5
glob.glob( '*' + os.path.sep)ではなく、[os.path.isdir(dir)if if dir。for glob.glob( "*")のdirのディレクトリ]
Eamonn MR

8

os.listdir()を使用してそれを追加するだけでは、「非常に単純なos.walk()。next()[1]と比較して多くの処理が必要」ではありません。これは、os.walk()が内部でos.listdir()を使用するためです。実際、一緒にテストすると:

>>>> import timeit
>>>> timeit.timeit("os.walk('.').next()[1]", "import os", number=10000)
1.1215229034423828
>>>> timeit.timeit("[ name for name in os.listdir('.') if os.path.isdir(os.path.join('.', name)) ]", "import os", number=10000)
1.0592019557952881

os.listdir()のフィルタリングはわずかに高速です。


2
Python 3.5に入ると、ディレクトリの内容をより速く取得できます:python.org/dev/peps/pep-0471
foz

1
pep-0471- scandirパッケージ-PyPIにインストール可能なパッケージとしてP​​ython 2.6以降で利用できます。それはの交換を提供しos.walkos.listdirそれははるかに高速です。
フォズ

6

非常にシンプルでエレガントな方法は、これを使用することです。

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

このスクリプトを、フォルダー名が必要な同じフォルダーで実行します。これにより、直接のフォルダー名のみが正確に示されます(フォルダーの完全パスがない場合)。


6

リスト内包表記を使用して、

[a for a in os.listdir() if os.path.isdir(a)]

一番簡単な方法だと思います


2

ここでは初心者なので、まだ直接コメントすることはできませんが、hereΩΤΖΙΟΥの回答の次の部分に追加したい小さな修正があります

完全パス名を使用する場合は、次の関数を使用してください:

def listdirs(folder):  
  return [
    d for d in (os.path.join(folder, d1) for d1 in os.listdir(folder))
    if os.path.isdir(d)
]

まだpython <2.4の場合:内部構造はタプルではなくリストである必要があるため、次のように読みます。

def listdirs(folder):  
  return [
    d for d in [os.path.join(folder, d1) for d1 in os.listdir(folder)]
    if os.path.isdir(d)
  ]

そうしないと、構文エラーが発生します。


久しぶりですが、この最初の例は本当に役に立ちました。
インバーローズ

1
ご使用のバージョンはジェネレーター式をサポートしていないため、構文エラーが発生します。これらはPython 2.4で導入されましたが、リスト内包表記はPython 2.0以降で利用可能です。
awatts 2013

1
[x for x in os.listdir(somedir) if os.path.isdir(os.path.join(somedir, x))]


1
scanDir = "abc"
directories = [d for d in os.listdir(scanDir) if os.path.isdir(os.path.join(os.path.abspath(scanDir), d))]

0

ディレクトリがない場合でも失敗しない、より安全なオプション。

def listdirs(folder):
    if os.path.exists(folder):
         return [d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d))]
    else:
         return []


0

Python 3.4はpathlibモジュールを標準ライブラリに導入ました。これは、ファイルシステムパスを処理するためのオブジェクト指向アプローチを提供します。

from pathlib import Path

p = Path('./')
[f for f in p.iterdir() if f.is_dir()]

-1
-- This will exclude files and traverse through 1 level of sub folders in the root

def list_files(dir):
    List = []
    filterstr = ' '
    for root, dirs, files in os.walk(dir, topdown = True):
        #r.append(root)
        if (root == dir):
            pass
        elif filterstr in root:
            #filterstr = ' '
            pass
        else:
            filterstr = root
            #print(root)
            for name in files:
                print(root)
                print(dirs)
                List.append(os.path.join(root,name))
            #print(os.path.join(root,name),"\n")
                print(List,"\n")

    return List
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.