아래 디렉토리를 파지 않고 os.walk


103

os.walk내가 제공 한 디렉토리의 파일 만 반환하도록 제한 하려면 어떻게합니까 ?

def _dir_list(self, dir_name, whitelist):
    outputList = []
    for root, dirs, files in os.walk(dir_name):
        for f in files:
            if os.path.splitext(f)[1] in whitelist:
                outputList.append(os.path.join(root, f))
            else:
                self._email_to_("ignore")
    return outputList

2
가능한 다양한 접근 방식과 그에 따른 모든 경고가이 기능을 Python 표준 라이브러리에 추가해야한다는 또 다른 경우입니다.
개미

files_with_full_path = [f.path for f in os.scandir(dir) if f.is_file()]. 파일 이름 만 필요한 경우 f.name대신 f.path. 이것은 가장 빠른 솔루션이며 walk또는 어떤 것보다 훨씬 빠릅니다 . stackoverflow.com/a/40347279/2441026을listdir 참조하십시오 .
user136036

답변:


105

walklevel기능을 사용하십시오 .

import os

def walklevel(some_dir, level=1):
    some_dir = some_dir.rstrip(os.path.sep)
    assert os.path.isdir(some_dir)
    num_sep = some_dir.count(os.path.sep)
    for root, dirs, files in os.walk(some_dir):
        yield root, dirs, files
        num_sep_this = root.count(os.path.sep)
        if num_sep + level <= num_sep_this:
            del dirs[:]

처럼 작동 os.walk하지만 level재귀의 깊이를 나타내는 매개 변수를 전달할 수 있습니다 .


3
이 기능이 실제로 전체 구조를 "걷고"특정 지점 아래의 항목을 삭제합니까? 아니면 더 영리한 일이 일어나고 있습니까? 코드로 이것을 확인하는 방법도 모르겠습니다. --python 초보자
mathtick 2010-08-19

1
@mathtick : 원하는 수준 이하의 디렉터리가 발견되면 모든 하위 디렉터리가 다음 검색을 위해 하위 디렉터리 목록에서 제거됩니다. 그래서 그들은 "걷지"않을 것입니다.
nosklo

2
디렉토리를 "삭제"하는 방법에 어려움을 겪고 있었기 때문에 이것을 +1했습니다. 나는 시도했다 dirs = []dirs = None하지만, 그 작동하지 않았다. map(dirs.remove, dirs)작동했지만 원치 않는 '[없음]'메시지가 인쇄되었습니다. 그렇다면 왜 del dirs[:]구체적으로?
Zach Young

4
topdown=Falseos.walk에서 사용할 때는 작동하지 않습니다 . 문서 의 네 번째 단락을 참조하십시오 .Modifying dirnames when topdown is False has no effect on the behavior of the walk, because in bottom-up mode the directories in dirnames are generated before dirpath itself is generated.
dthor

3
@ZacharyYoung은 dirs = []하고 dirs = None그들은 단지 이름에 새로운 관계가없는 객체와 할당을 만들 수 있기 때문에 작동하지 않습니다 dirs. 원래 목록 객체는 이름이 아닌 제자리에서 수정해야합니다 dirs.
nosklo

206

os.walk를 사용하지 마십시오.

예:

import os

root = "C:\\"
for item in os.listdir(root):
    if os.path.isfile(os.path.join(root, item)):
        print item

1
@ 576i로이 파일 및 디렉토리를 구분하지 않습니다

4
@Alexandr os.path.isfileos.path.isdir사용하여 차별화 할 수 있습니다. 이후 나는 그것을 얻을하지 않습니다 os.path.isfile'08 년부터 샘플 코드에 당신의 의견은 '16에서입니다. 이것은 분명히 더 나은 대답입니다. 당신이 디렉토리를 걸어 다니는 것이 아니라 그것을 나열하려는 것이기 때문입니다.
Daniel F

@DanielF, 여기서 의미하는 바 walk는 모든 항목을 반복해야하는 동시에 별도의 디렉토리 및 파일 목록을 즉시 제공한다는 것입니다.

그래. 실제로 Alex의 대답은 더 나은 것 같 .next()으며 (사용 ) 귀하의 아이디어에 훨씬 더 가깝습니다.
Daniel F

Python 3.5에는 os.scandir보다 정교한 파일 또는 디렉토리 객체 상호 작용을 허용 하는 기능이 있습니다. 보기 내 대답은 아래
ascripter

48

해결책은 실제로 매우 간단하다고 생각합니다.

사용하다

break

for 루프의 첫 번째 반복 만 수행하려면 더 우아한 방법이 있어야합니다.

for root, dirs, files in os.walk(dir_name):
    for f in files:
        ...
        ...
    break
...

os.walk를 처음 호출하면 현재 디렉토리에 대한 튤립을 반환 한 다음 다음 디렉토리의 내용을 루프합니다.

원본 스크립트를 가져 와서 휴식을 추가하십시오 .

def _dir_list(self, dir_name, whitelist):
    outputList = []
    for root, dirs, files in os.walk(dir_name):
        for f in files:
            if os.path.splitext(f)[1] in whitelist:
                outputList.append(os.path.join(root, f))
            else:
                self._email_to_("ignore")
        break
    return outputList

9
이것은 받아 들여진 대답이어야합니다. "for f in files"루프 뒤에 "break"를 추가하면 재 귀성이 중지됩니다. topdown = True인지 확인할 수도 있습니다.
Alecz

23

사용 제안 listdir은 좋은 것입니다. Python 2에서 귀하의 질문에 대한 직접적인 대답은 root, dirs, files = os.walk(dir_name).next().

동등한 Python 3 구문은 다음과 같습니다. root, dirs, files = next(os.walk(dir_name))


1
오, 나는 그로부터 온갖 종류의 재미있는 오류를 얻었습니다. ValueError : 압축을 풀기에 너무 많은 값
Setori

1
좋은! 그래도 해킹처럼 느껴집니다. 엔진을 켰지 만 한 바퀴 만 돌리고 열쇠를 당기면 죽을 때와 같습니다.
Daniel F

이것을 우연히 발견했습니다. root, dirs, files = os.walk(dir_name).next()제공합니다AttributeError: 'generator' object has no attribute 'next'
Evan

3
@Evan, 아마도 이것은 2008에서 왔고 Python 2 구문을 사용하기 때문입니다. Python 3에서는 작성할 수 root, dirs, files = next(os.walk(dir_name))있으며 변수 root, dirs, filesdir_name수준 에서 생성기의 변수에만 해당 합니다.
CervEd

13

os.listdir()주어진 디렉토리에서 이름 목록 (파일과 디렉토리 모두)을 반환하는 것을 사용할 수 있습니다 . 파일과 디렉토리를 구별해야하는 경우 os.stat()각 이름을 호출하십시오 .


9

최상위 디렉토리보다 더 복잡한 요구 사항이있는 경우 (예 : VCS 디렉토리 무시 등) 디렉토리 목록을 수정하여 os.walk가 반복되지 않도록 할 수도 있습니다.

즉 :

def _dir_list(self, dir_name, whitelist):
    outputList = []
    for root, dirs, files in os.walk(dir_name):
        dirs[:] = [d for d in dirs if is_good(d)]
        for f in files:
            do_stuff()

참고-목록을 리 바인드하는 것보다 변경하는 데주의하십시오. 분명히 os.walk는 외부 리 바인딩에 대해 알지 못합니다.


6
for path, dirs, files in os.walk('.'):
    print path, dirs, files
    del dirs[:] # go only one level deep

4

와 같은 아이디어 listdir이지만 더 짧습니다.

[f for f in os.listdir(root_dir) if os.path.isfile(os.path.join(root_dir, f))]

3

내 2 펜스를 던지는 것 같은 느낌.

baselevel = len(rootdir.split("\\"))
for subdirs, dirs, files in os.walk(rootdir):
    curlevel = len(subdirs.split("\\"))
    if curlevel <= baselevel + 1:
        [do stuff]

2

Python 3에서는 다음과 같이 할 수있었습니다.

import os
dir = "/path/to/files/"

#List all files immediately under this folder:
print ( next( os.walk(dir) )[2] )

#List all folders immediately under this folder:
print ( next( os.walk(dir) )[1] )

이것은 Python 2에서도 작동합니다. 두 번째 레벨을 얻는 방법은 무엇입니까?

2

이후 파이썬 3.5 당신이 사용할 수있는 os.scandir대신에 os.listdir. 문자열 대신 DirEntry개체 의 반복자를 반환합니다. 문서에서 :

scandir()대신을 사용하면 listdir()파일 유형 또는 파일 속성 정보가 필요한 코드의 성능이 크게 향상 될 수 있습니다 DirEntry. 운영 체제가 디렉터리를 스캔 할 때 제공하는 경우 개체가이 정보를 노출 하기 때문 입니다. 모든 DirEntry방법은 시스템 호출을 수행 할 수 있지만 is_dir()is_file()보통 심볼릭 링크에 대한 시스템 호출을 필요로; DirEntry.stat()Unix에서는 항상 시스템 호출이 필요하지만 Windows의 심볼릭 링크에는 하나만 필요합니다.

객체의 이름에 액세스 할 수 있으며 DirEntry.name이를 통해 다음 출력과 동일합니다.os.listdir


1
뿐만 아니라 "수"당신은 당신이 사용 해야 사용 scandir()이 A의로, 많은 것보다 더 빨리 listdir(). 벤치 마크는 stackoverflow.com/a/40347279/2441026 에서 확인하세요 .
user136036

1

다음을 수행 할 수도 있습니다.

for path, subdirs, files in os.walk(dir_name):
    for name in files:
        if path == ".": #this will filter the files in the current directory
             #code here

2
이 모든 하위 디렉토리와 파일을 불필요하게 반복하지 않습니까?
Pieter

0

이것이 내가 그것을 해결 한 방법입니다

if recursive:
    items = os.walk(target_directory)
else:
    items = [next(os.walk(target_directory))]

...

0

listdir을 사용할 때 캐치가 있습니다. os.path.isdir (식별자)는 절대 경로 여야합니다. 하위 디렉토리를 선택하려면 다음을 수행하십시오.

for dirname in os.listdir(rootdir):
  if os.path.isdir(os.path.join(rootdir, dirname)):
     print("I got a subdirectory: %s" % dirname)

대안은 os.path.join ()없이 테스트를 수행하기 위해 디렉토리로 변경하는 것입니다.


0

이 스 니펫을 사용할 수 있습니다.

for root, dirs, files in os.walk(directory):
    if level > 0:
        # do some stuff
    else:
        break
    level-=1

0

제외 목록을 만들고 fnmatch를 사용하여 디렉터리 구조를 건너 뛰고 프로세스를 수행합니다.

excludes= ['a\*\b', 'c\d\e']
for root, directories, files in os.walk('Start_Folder'):
    if not any(fnmatch.fnmatch(nf_root, pattern) for pattern in excludes):
        for root, directories, files in os.walk(nf_root):
            ....
            do the process
            ....

'포함'과 동일 :

if **any**(fnmatch.fnmatch(nf_root, pattern) for pattern in **includes**):

0

왜 단순히를 사용 range하고 os.walk과 함께 zip? 최상의 솔루션은 아니지만 작동합니다.

예를 들면 다음과 같습니다.

# your part before
for count, (root, dirs, files) in zip(range(0, 1), os.walk(dir_name)):
    # logic stuff
# your later part

파이썬 3에서 나를 위해 작동합니다.

또한 : A break는 너무 간단합니다. (@Pieter의 답변을보세요)


0

Alex의 대답에 약간의 변경이 있지만 다음을 사용합니다 __next__().

print(next(os.walk('d:/'))[2]) 또는 print(os.walk('d:/').__next__()[2])

[2]fileroot, dirs, file다른 답변에서 언급


0

os.walk가 찾은 모든 디렉토리의 루트 폴더 변경. 루트 == 디렉토리인지 확인하는 해결사

def _dir_list(self, dir_name, whitelist):
    outputList = []
    for root, dirs, files in os.walk(dir_name):
        if root == dir_name: #This only meet parent folder
            for f in files:
                if os.path.splitext(f)[1] in whitelist:
                    outputList.append(os.path.join(root, f))
                else:
                    self._email_to_("ignore")
    return outputList

0
import os

def listFiles(self, dir_name):
    names = []
    for root, directory, files in os.walk(dir_name):
        if root == dir_name:
            for name in files:
                names.append(name)
    return names

1
안녕하세요 Rich 님, Stack Overflow에 오신 것을 환영합니다! 제한된 단기 도움을 제공 할 수있는이 코드 스 니펫에 감사드립니다. 적절한 설명 이것이 문제에 대한 좋은 해결책 인 이유를 보여줌으로써 장기적인 가치를 크게 향상시키고 다른 유사한 질문을 가진 미래의 독자에게 더 유용하게 만들 것입니다. 제발 편집 당신이 만든 가정 등 일부 설명을 추가 할 답변을.
kenny_k
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.