os에는 listdir, scandir, walk가 있습니다. 이 중 os.walk는 무엇을 하는 함수일까요?

 


 먼저 제가 탐색할 폴더를 '.'라고 해 보겠습니다. 이 폴더 아래에는 폴더 a, 파일 b, c가 있고, 폴더 a 밑에는 파일 a, b가 있습니다. 이 때, listdir과 scandir은 아래 회색친 부분만 탐색합니다.

 

 

 1뎁스만 탐색하는 것을 볼 수 있어요. 이에 비해, walk는 . 아래에 있는 모든 파일과 폴더들을 탐색합니다. 단, 아무런 설정을 하지 않으면, 바로가기와 같은 것들은 제외하고 탐색하긴 합니다. 제가 탐색할 폴더 . 밑에 그러한 것이 없다고 가정하면, 회색 부분이 walk가 탐색하는 범위가 됩니다.

 

 

 그러니, 언제 써야 할 지는 쉽게 알 수 있습니다. 어떤 폴더를 기준으로 재귀적으로 탐색이 필요할 때 os.walk를 쓴다는 것 정도만 이해하고 넘어가셔도 무난합니다.

 

 


 함수 설명을 보면 tree generator라고 되어 있습니다. generation이 될 때 마다, dirpath와 dirnames, filenames 이렇게 3개가 튜플로 떨어지게 됩니다. 이걸 어떻게 쓰는지 간단하게 예시를 보도록 하겠습니다.

 

 

 먼저 현재 main.py가 있는 상대 경로를 기준으로 재귀적인 탐색을 하려고 합니다. 그러면 os.walk(".")를 호출하면 됩니다. 어렵지 않습니다. 이들이 for loop를 돌면서 어떻게 출력되는지 보겠습니다.

 

 

 먼저 1번째는 경로를 의미합니다. 다음 2번째는 해당 경로에 있는 디렉토리를, 3번째는 해당 경로에 있는 디렉토리가 아닌 파일들을 의미합니다. 2번째와 3번째 요소가 비어 있는 경우는, 폴더 안에 아무것도 없다는 것입니다. venv 밑에 Include 폴더로 들어가 보겠습니다.

 

 

 아무것도 없음을 알 수 있습니다.

 

 


 간단하게 파일 수를 체크하는 프로그램도 만들 수 있습니다.

 

 4번째 줄을 봅시다. 먼저 list(k[2] for k in t)는, 현재 위치인 "." 하위 (하위의 하위 등도 모두 포함)에 있는 모든 폴더 내 있는 파일들을 돌려줍니다. 예를 들자면, "." 밑에 아래와 같은 구조로 폴더와 파일들이 있다고 해 봅시다.

 

 

 이 때, list(k[2] for k in t)의 결과는, [[a, b], [b, c]]가 됩니다. 이 list에는 iterable한 객체 2개가 있는데요. [a, b], [b, c]입니다. 이들에 대해, len을 적용하게 됩니다. 그러면 iterator는 2, 2를 탐색하게 될 겁니다. 그러면 sum(iterator)는 2에 2를 더한 4가 됩니다. 결국, 3번째 줄은 바로 가기 등을 제외한 현재 폴더 밑에 있는 모든 파일의 갯수를 구합니다. 

 

 

 1461이 나오네요. 실제 폴더 정보를 보면 어떨까요?

 

 

 똑같이 나옵니다. 단 두 줄로, 폴더 내에 있는, sym link 같은 것을 제외한 모든 파일의 개수를 셀 수 있습니다.