현재 디렉토리의 모든 서브 디렉토리 목록 가져 오기


답변:


602

즉각적인 서브 디렉토리 또는 트리 바로 아래의 모든 디렉토리를 의미합니까?

어느 쪽이든, 당신 os.walk은 이것을 할 수 있습니다 :

os.walk(directory)

각 하위 디렉토리에 대한 튜플을 생성합니다. 3- 튜플의 첫 번째 항목은 디렉토리 이름이므로

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

모든 하위 디렉토리를 재귀 적으로 제공해야합니다.

튜플의 두 번째 항목은 첫 번째 위치에있는 항목의 하위 디렉토리 목록이므로이를 대신 사용할 수는 있지만 크게 절약 할 수는 없습니다.

그러나 즉시 하위 디렉토리를 제공하기 위해 사용할 수 있습니다.

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

아니면 다른 솔루션 이미 게시하여 참조 os.listdiros.path.isdir"에 포함, 파이썬에서 즉시 모든 하위 디렉터리를 얻을 수 있습니다 "를.


7
os.walk가 트리플 (루트, 디렉토리, 파일)을 반환한다고 생각합니다. 즉, dirs에는 반복되는 항목이 많이 있습니다. 디렉토리를 통해 재귀하는 더 효율적인 방법이 있습니까?
mathtick

22
사용하지 마십시오 os.walk('.').next()[1]또는 os.walk('.').__next__()[1]직접. 대신 내장 함수를 사용하십시오.이 함수 next()Python 2 (doc 참조)Python 3 (doc 참조 ) 모두에서 사용할 수 있습니다 . 예를 들면 다음과 같습니다 next(os.walk('.'))[1]..
Lucio Paiva

1
@Lucio 왜 os.walk('.').next()[1]직접 사용하는 것이 나쁜 가요?
wisbucky

8
@wisbucky iteraror.__next__()내부 방법 이므로 PEP-3114 iterator.next()next()따라 사용법을 내장으로 전환해야 하므로 나쁜 습관 입니다. 참조 PEP-3114 2007 년에 승인되었다
루시오 PAIVA

16
+ 솔루션 간의 성능 차이에 관심이있는 사람은 다음 os.walk과 같이 10,000 개의 하위 디렉토리 (아래 계층에 수백만 개의 파일 포함)가있는 디렉토리에서 테스트했으며 성능 차이는 무시할 수 있습니다. "10 개 루프, 3 최고 : 루프 당 44.6 밀리 초"와 + : "10 개 루프, 3 최고 : 루프 당 45.1 밀리 초"os.listdiros.path.isdiros.walkos.listdiros.path.isdir
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
이 접근 방식에서 '.'에서 실행되지 않으면 경로 문제를 처리해야합니다.
daspostloch

4
당신은 ( '.')을 CWD를 사용하지 않는 경우이 작업을 수행하지 않는 한 그냥 머리 위로는,이 작동하지 않습니다 os.path.joino전체 경로를 얻을 그렇지 않으면 isdir(0)항상 false를 반환합니다
제임스 맥마흔

5
게시물이 위에 언급 된 두 가지 문제에 대한 픽스로 업데이트 된 것으로 보입니다.
cgmb

1
os.path.join두 번 전화하지 않으려면 먼저 다음을 사용하여 목록에 os.path.isdirfilter(os.path.isdir, [os.path.join(d, o) for o in os.listdir(d)])
참가한

155

당신은 그냥 사용할 수 있습니다 glob.glob

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

의 후행 /을 잊지 마십시오 *.


좋은. 단순한. 만, 그것은 후행 잎 /이름에
juanmirocks

9
/폴더 구분자로 가정 할 수없는 경우 다음 과 같이하십시오.glob(os.path.join(path_to_directory, "*", ""))
juanmirocks

1
하위 디렉토리에서는 작동하지 않습니다! glob를 사용하려면 여기에 완전한 대답 이 있습니다 .Glob ()을 사용하여 파이썬에서 파일을 재귀 적으로 찾기?
poppie

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.walk약간 빠른 - - 또는 ▶ fast_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

서브 디렉토리에서 모든 서브 디렉토리를 찾을 수있는 재귀 솔루션이 필요한 경우 이전에 제안한대로 walk를 사용하십시오.

당신은 현재 디렉토리의 하위 디렉토리가 필요한 경우, 결합 os.listdiros.path.isdir




19

os.listdir (path)를 사용하여 Python 2.7에서 서브 디렉토리 및 파일 목록을 가져올 수 있습니다.

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

59
여기에는 파일도 포함됩니다.
Tarnay Kálmán

2
'dir'은 목록을 구성하는 객체가 아니라 컨테이너 디렉토리를 나타내므로 혼동됩니다. 초보자를 위해 단선 답변을 확인하십시오.
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 만 반환한다는 것입니다.
denson

행을 약간 수정하면 현재 디렉토리 외부에서 작동합니다. subdirs = filter (os.path.isdir, [os.listdir (dir)에서 x의 경우 os.path.join (dir, x)])
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

이 질문은 오래 전에 답변되었지만. pathlibWindows 및 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]파이썬에서 무엇이 호출되어 그것을 찾을 수 있습니까?
shinzou

2
@shinzou 그것은 목록 이해입니다. 매우 유용합니다. dict 이해력도 찾아보십시오.
KurtB

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

1
@AbhishekParikh x는 목록에서 파일 을 필터링하기 위해 명령을 사용하는 파일 및 폴더를 반환 os.listdir(d)하기 때문에 생성 된 목록의 항목입니다 . listdirfilteros.path.isdir
제임스 버크 19

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

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에서 구현되었다는 것을 읽을 수 있다고 맹세 할 수는 있지만 잘못된 것 같습니다.
Alberto 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.