Python 목록 디렉터리, 하위 디렉터리 및 파일


130

주어진 디렉토리의 모든 디렉토리, 하위 디렉토리 및 파일을 나열하는 스크립트를 만들려고합니다.
나는 이것을 시도했다 :

import sys,os

root = "/home/patate/directory/"
path = os.path.join(root, "targetdirectory")

for r,d,f in os.walk(path):
    for file in f:
        print os.path.join(root,file)

안타깝게도 제대로 작동하지 않습니다.
모든 파일을 얻지 만 완전한 경로는 얻지 못합니다.

예를 들어 dir 구조체는 다음과 같습니다.

/home/patate/directory/targetdirectory/123/456/789/file.txt

다음과 같이 인쇄됩니다.

/home/patate/directory/targetdirectory/file.txt

내가 필요한 것은 첫 번째 결과입니다. 어떤 도움이라도 대단히 감사하겠습니다! 감사.

답변:


225

디렉토리 와 파일 이름os.path.join 을 연결하는 데 사용 합니다 .

for path, subdirs, files in os.walk(root):
    for name in files:
        print os.path.join(path, name)

사용 이 올바르지 path않으므로 root연결이 아닌 사용에 유의하십시오 root.


Python 3.4에서는 더 쉬운 경로 조작을 위해 pathlib 모듈이 추가되었습니다. 따라서에 해당하는 os.path.join것은 다음과 같습니다 .

pathlib.PurePath(path, name)

의 장점은 pathlib경로에서 다양한 유용한 방법을 사용할 수 있다는 것입니다. 구체적인 Path변형 을 사용하면 디렉토리로 변경, 경로 삭제, 가리키는 파일 열기 등과 같은 실제 OS 호출을 수행 할 수도 있습니다.


이것은 "python에서 모든 파일을 재귀 적으로 가져 오는 방법"과 관련하여 많은 질문에 대한 유일한 유용한 답변입니다.
harrisonfooord

이해 목록 : all_files = [os.path.join (path, name) for name in files for path, subdirs, files in os.walk (folder)]
Nir

45

경우에 따라 ... 일부 패턴 (예 : * .py)과 일치하는 디렉토리 및 하위 디렉토리의 모든 파일 가져 오기 :

import os
from fnmatch import fnmatch

root = '/some/directory'
pattern = "*.py"

for path, subdirs, files in os.walk(root):
    for name in files:
        if fnmatch(name, pattern):
            print os.path.join(path, name)

10

다음은 한 줄짜리입니다.

import os

[val for sublist in [[os.path.join(i[0], j) for j in i[2]] for i in os.walk('./')] for val in sublist]
# Meta comment to ease selecting text

가장 바깥 쪽 val for sublist in ...루프는 목록을 1 차원으로 평평하게 만듭니다. j루프는 모든 파일의 기본 이름의 목록을 수집하고 현재 경로에 합류했다. 마지막으로 i루프는 모든 디렉토리와 하위 디렉토리를 반복합니다.

이 예에서는 호출 ./에서 하드 코딩 된 경로를 사용하므로 os.walk(...)원하는 경로 문자열을 보완 할 수 있습니다.

참고 : os.path.expanduser및 / 또는 다음 과 os.path.expandvars같은 경로 문자열에 사용할 수 있습니다.~/

이 예제 확장 :

파일 기본 이름 테스트 및 디렉토리 이름 테스트에 쉽게 추가 할 수 있습니다.

예를 들어 *.jpg파일 테스트 :

... for j in i[2] if j.endswith('.jpg')] ...

또한 .git디렉토리 제외 :

... for i in os.walk('./') if '.git' not in i[0].split('/')]

작동하지만 .git 디렉토리를 제외하려면 '.git'이 경로에 없는지 확인해야합니다.
Roman Rdgz

네. '.git'가 i [0] .split ( '/')에없는 경우 여야 함]
Roman Rdgz

os.walk수동 dirlisting 루프보다 권장 합니다. 생성기는 훌륭합니다.
ThorSummoner

9

여기에 답변을 작성하면 댓글을 달 수 없습니다. 이것은 내가 본 것 중 가장 명확한 한 줄입니다.

import os
[os.path.join(path, name) for path, subdirs, files in os.walk(root) for name in files]

4

내가 만든이 샘플을 볼 수 있습니다. 더 이상 사용되지 않는 os.path.walk 함수를 사용합니다.

root = "Your root directory"
ex = ".txt"
where_to = "Wherever you wanna write your file to"
def fileWalker(ext,dirname,names):
    '''
    checks files in names'''
    pat = "*" + ext[0]
    for f in names:
        if fnmatch.fnmatch(f,pat):
            ext[1].append(os.path.join(dirname,f))


def writeTo(fList):

    with open(where_to,"w") as f:
        for di_r in fList:
            f.write(di_r + "\n")






if __name__ == '__main__':
    li = []
    os.path.walk(root,fileWalker,[ex,li])

    writeTo(li)

4

좀 더 간단한 한 줄 :

import os
from itertools import product, chain

chain.from_iterable([[os.sep.join(w) for w in product([i[0]], i[2])] for i in os.walk(dir)])

2

여기의 모든 예제는 walk(with join)를 사용하기 때문에 좋은 예제와 비교를 보여주고 싶습니다 listdir.

import os, time

def listFiles1(root): # listdir
    allFiles = []; walk = [root]
    while walk:
        folder = walk.pop(0)+"/"; items = os.listdir(folder) # items = folders + files
        for i in items: i=folder+i; (walk if os.path.isdir(i) else allFiles).append(i)
    return allFiles

def listFiles2(root): # listdir/join (takes ~1.4x as long) (and uses '\\' instead)
    allFiles = []; walk = [root]
    while walk:
        folder = walk.pop(0); items = os.listdir(folder) # items = folders + files
        for i in items: i=os.path.join(folder,i); (walk if os.path.isdir(i) else allFiles).append(i)
    return allFiles

def listFiles3(root): # walk (takes ~1.5x as long)
    allFiles = []
    for folder, folders, files in os.walk(root):
        for file in files: allFiles+=[folder.replace("\\","/")+"/"+file] # folder+"\\"+file still ~1.5x
    return allFiles

def listFiles4(root): # walk/join (takes ~1.6x as long) (and uses '\\' instead)
    allFiles = []
    for folder, folders, files in os.walk(root):
        for file in files: allFiles+=[os.path.join(folder,file)]
    return allFiles


for i in range(100): files = listFiles1("src") # warm up

start = time.time()
for i in range(100): files = listFiles1("src") # listdir
print("Time taken: %.2fs"%(time.time()-start)) # 0.28s

start = time.time()
for i in range(100): files = listFiles2("src") # listdir and join
print("Time taken: %.2fs"%(time.time()-start)) # 0.38s

start = time.time()
for i in range(100): files = listFiles3("src") # walk
print("Time taken: %.2fs"%(time.time()-start)) # 0.42s

start = time.time()
for i in range(100): files = listFiles4("src") # walk and join
print("Time taken: %.2fs"%(time.time()-start)) # 0.47s

따라서 직접 볼 수 있듯이 listdir버전이 훨씬 더 효율적입니다. (그리고 그것은 join느립니다)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.