os.walk에서 디렉토리 제외


148

os.walk ()를 사용하여 디렉토리 트리로 내려간 스크립트를 작성하고 특정 파일 확장자와 일치하는 각 파일을 방문합니다. 하지만, 내 도구는 차례로 포함하는 서브 디렉토리 포함에 사용됩니다 디렉토리 나무의 일부 이후 LOT 물건 (이 스크립트의 목적을 위해) 쓸모없는의를, I는 사용자가 지정하는 내가 옵션을 추가 거라고 생각 순회에서 제외 할 디렉토리 목록

이것은 os.walk ()로 충분합니다. 결국, os.walk ()에 의해 생성 된 각각의 파일 / 디렉토리를 실제로 방문할지 아니면 그냥 건너 뛸지를 결정하는 것은 나에게 달려 있습니다. 문제는 예를 들어 다음과 같은 디렉토리 트리가있는 경우입니다.

root--
     |
     --- dirA
     |
     --- dirB
     |
     --- uselessStuff --
                       |
                       --- moreJunk
                       |
                       --- yetMoreJunk

그리고 나는 uselessStuff 와 그 모든 자식 을 제외하고 싶습니다 . os.walk ()는 uselessStuff의 모든 (잠재적으로 수천 개의) 하위 디렉토리로 내려갈 것입니다. 이상적인 세계에서 os.walk ()에게 더 이상 쓸모없는 Stuff의 자식을 생성하는 것을 귀찮게 하지는 않지만 내 지식에는 그렇게 할 수있는 방법이 없습니다 (있는가?).

누구든지 아이디어가 있습니까? 어쩌면 그런 것을 제공하는 타사 라이브러리가 있습니까?

답변:


243

내부 수정 dirs 다음에 방문한 (후속) 파일 및 디렉토리를 제거합니다 os.walk.

# exclude = set([...])
for root, dirs, files in os.walk(top, topdown=True):
    dirs[:] = [d for d in dirs if d not in exclude]

도움말 (os.walk)에서 :

하향식이 true이면 호출자는 디렉토리 이름 목록을 제자리에서 수정할 수 있으며 (예 : 델 또는 슬라이스 지정을 통해), 디렉토리 이름에 디렉토리 이름이 남아있는 서브 디렉토리로만 이동합니다. 이것은 검색을 제거하는 데 사용할 수 있습니다 ...


31
dirs[:] =?
ben

56
@ben : 제자리에서dirs[:] = value 수정합니다 . 컨테이너를 변경하지 않고 목록의 내용을 변경합니다. 언급 했듯이 하위 디렉토리를 통과하는 방식에 영향을 주려는 경우에 필요합니다 . ( 원본을 수정하지 않고 변수 를 새 목록에 재 지정 (또는 "바인딩")합니다 .)dirs dirshelp(os.walk)os.walkdirs = valuedirsdirs
unutbu

6
당신은 또한 사용할 수 있습니다 filter():dirs[:] = list(filter(lambda x: not x in exclude, dirs))
NuclearPeon

2
@ p014k :에서 (또는 원하는 다른 것을) 제외 한 후 호출 os.walk하고 생성 하는 자체 생성기 함수를 작성할 수 있습니다 . root, dirs, files.gitdirs
unutbu December

3
@unutbu 한 가지 경우에,이 최적화는 순회 시간을 100 초 이상에서 2 초로 줄였다는 것을 알려줍니다. 그것이 내가 가치있는 최적화라고 부르는 것입니다. : D
antred

7

... O (n ** 2) 대 O (n) 시간의 비용으로 디렉토리 를 제외 하려는 의도를 감안할 때 @unutbu의 훌륭한 답변의 대안 양식을 조금 더 직접 읽습니다 .

( list(dirs)올바른 실행을 위해서는 dirs 목록의 복사본을 만들어야합니다 )

# exclude = set([...])
for root, dirs, files in os.walk(top, topdown=True):
    [dirs.remove(d) for d in list(dirs) if d in exclude]

5
약간의 메모리 비용으로 더 직접적이기를 원한다면을 작성하는 것이 좋습니다 dirs[:] = set(dirs) - exclude. 적어도 여전히 \ $ O (n) \ $이고 부작용에 대해서만 이해력을
쌓지

3
이것은 나쁘지 않지만 관용적 인 파이썬은 아닙니다.
Torsten Bronger

for d in list(dirs)조금 이상합니다. dirs이미 목록입니다. 그리고 당신이 가진 것은 실제로 목록 이해력이 아닙니다. dirs.remove(d)아무것도 반환하지 않으므로 Nones로 가득 찬 목록으로 끝납니다 . @Torsten에 동의합니다.
seanahern
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.