2013-03-06 2 views
2

나는 파이썬에서 특정 디렉토리의 모든 손자를 얻으려고합니다. 성능상의 이유로 OS 기능을 루프 (네트워크 파일 시스템)라고 부르기를 원하지 않습니다. 이것은 내가 지금 가지고있는 것입니다. 이 작업을 수행하는 더 간단한 방법이 있습니까?하나의 OS 호출로 파이썬에서 디렉토리의 모든 손자를 얻는 방법

dirTree = os.walk(root) 
children = [os.path.join(root, x) for x in dirTree.next()[1]] 
grandChildren = [] 
for root, dirs, files in dirTree: 
    if root in children: 
     for dir in dirs: 
      grandChildren.append(os.path.join(root, dir)) 

편집 : os.walk에 대한 전화가 게으른 지 아닌지에 대해 명확하지 않습니다. 내 의도는 전체 트리는 내 전화 후에 기억에 있어야하지만 나는 그것에 대해 잘 모르겠다.

+0

당신이'unipath' 모듈 봤어 할 수있는뿐만 아니라 모든 파일을 알고? –

+0

[이 답변] (http://stackoverflow.com/a/4117594/8747) 빛을 흘릴 수도 있습니다. –

+0

2 세 이하의 모든 세대의 손주 또는 모든 자손에만 관심이 있으십니까? 즉, '루트/a/b/c/d'가 검색에 포함되거나 제외됩니까? –

답변

5

내가 바로 질문이 있어요합니다.

와일드 카드 표기법을 사용하여 glob를 사용하여 파일이나 디렉토리를 가져올 수 있습니다. 예를 들어, "/ home /"안에 모든 디렉토리를 가져올 수 있습니다. 또는

glob.glob('/home/*/*/') 

glob.glob('/home/*/*') 
+0

각 디렉토리의 하위 디렉토리 수를 알아야하기 때문에이 방법은별로 유용하지 않습니다. – msvalkon

+0

glob.iglob ('/ home/*/* /')]'의 dirpath에 대한 jjujuma :'grandChildren = [dirpath.rstrip (os.sep)]'는 코드와 동일한 목록을 생성합니다. 'rstrip()'은 목록에있는 디렉토리 경로에서 후행 경로 분리자를 제거합니다. @msvalkon : 나는 당신이 실수라고 생각합니다. – martineau

+0

@martineau ah yes'/ foo/bar'의 모든 서브 디렉토리로'grandChildren'을 이해했습니다. – msvalkon

1

POSIX도 Windows도 하나의 OS 호출에서 모든 데이터를 가져올 수 없습니다. 최소한 POSIX의 경우 디렉토리 당 세 개 (opendir, readdir, close), 디렉토리 항목 당 하나 (stat)가 추가됩니다.


다음 내용은 게시 한 것보다 적은 OS 호출을 발생시킬 것이라고 생각합니다. 예, os.walk() 전화는 게으르다. 즉, 전체 트리는 walk()에서 돌아 오면 메모리에 이 아니고이 아니지만 next()으로 전화하는 동안 조각으로 읽어야합니다.

따라서 제 버전은 1 차 자손 디렉토리에서만 읽을 수 있으며 직접 자식과 손자녀는 stat이됩니다. 귀하의 버전은 귀하의 디렉토리 구조만큼이나 모든 증손자를 위해 그 일을 할 것입니다.

root='.' 
grandChildren = [] 
for kid in next(os.walk('.'))[1]: 
    x = next(os.walk(os.path.join('.', kid))) 
    for grandKid in x[1]: # (or x[1]+x[2] if you care about regular files) 
    grandChildren.append(os.path.join(x[0], grandKid)) 

또는 루프 대신의 지능형리스트로 : 함수에 os.walk의를 고려해 마지막으로

import os 
root='.' 
grandChildren = [ 
    os.path.join(kid, grandKid) 
    for kid in next(os.walk(root))[1] 
    for grandKid in next(os.walk(os.path.join(root, kid)))[1]] 

: 테스트에서

def read_subdirs(dir='.'): 
    import os 
    return (os.path.join(dir,x) for x in next(os.walk(dir))[1]) 

root='.' 
grandChildren = [ 
    grandKid 
    for kid in read_subdirs(root) 
    for grandKid in read_subdirs(kid)] 


, 우리는 증조부모가있는 경우 제 버전이 stat 번보다 훨씬 적은 횟수로 걸리는 것을 볼 수 있습니다. 내 홈 디렉토리에서

는, 예를 들어, 나는 각각의 경우에 '.'root 세트 내 코드 (/tmp/a.py)와 당신 (/tmp/b.py를) 실행 :

$ strace -e stat python /tmp/a.py 2>&1 > /dev/null | egrep -c stat 
1245 
$ strace -e stat python /tmp/b.py 2>&1 > /dev/null | egrep -c stat 
36049 
관련 문제