Python으로 파일의 경로 및 목록 다루기
≡ 목차 (Table of Contents)
이 글은 더이상 업데이트 되지 않으며 대신 새 노트인 ⏍https://seorenn.github.io/article/python-path-tips.html , ⏍https://seorenn.github.io/article/python-file-dir-exists.html , ⏍https://seorenn.github.io/article/python-list-dir.html 등의 글에서 별도로 업데이트 될 예정입니다.
이 글은 Python으로 파일 및 디렉토리의 경로(path)나 파일 목록 구하기와 관련된 내용을 정리한다. 딱히 이런 분류로 글을 쓰는 건 개인적으로 자주 사용하고 자주 찾게 되는 내용이라 그렇지 별 다른 구분이 있는 것은 아니다.
경로에서 파일명만 얻기
os.path
모듈의 basename()
함수를 사용하면 경로에서 파일명만 문자열로 따로 얻을 수 있다.
>>> import os >>> os.path.basename('/foo/bar/test.txt') 'test.txt'
경로에서 디렉터리만 얻기
os.path
모듈의 dirname()
함수를 사용하면 해당 경로에서 디렉터리 부분만 문자열로 얻을 수 있다.
>>> import os >>> os.path.dirname('/foo/bar/test.txt') '/foo/bar'
파일명에서 확장자 분리하기
os.path
모듈의 splitext()
함수는 파일명에서 확장자를 분리하는 용도로 사용할 수 있다. 함수 이름에 주의하자.
>>> import os >>> os.path.splitext('test.txt') ('test', '.txt')
splitext
는 파일명 뿐만이 아니라 경로(path)에서도 동작한다. 예를 들어 /foo/bar/text.txt
를 입력할 경우 /foo/bar/text
와 .txt
로 분리된다.
경로에서 디렉터리와 파일 분리하기
이 경우에는 os.path
모듈의 split()
함수를 사용해보자.
>>> import os >>> os.path.split('/foo/bar/sample.txt') ('/foo/bar', 'sample.txt')
참고로 os.path.split()
함수는 경로에서 마지막 요소만을 분리해주는 용도다. 그래서 상위 디렉터리를 구하는 용도로도 사용할 수 있다.
>>> os.path.split('/foo/bar') ('/foo', 'bar')
파일 혹은 디렉토리 구분하기
os.path
모듈에 isfile()
과 isdir()
이라는 딱 적당한(?) 이름의 함수가 제공된다.
>>> import os >>> os.path.isfile('/foo/bar/some/file.txt') True >>> os.path.isdir('/foo/bar/some/file.txt') False
디렉터리 안의 파일 목록 얻기
여러 방법이 있겠지만 여기서는 os
모듈의 listdir
을 사용한 방법을 보자.
>>> import os >>> os.listdir('.') ['foo.a', 'bar.b', 'somedir', ...]
디렉터리 안의 모든 파일 및 디렉터리 목록 얻기
특정 디렉터리 안의 내용물을 서브 디렉터리까지 다 포함해서 목록을 구할려면 여러 방법이 있겠지만 이번에는 Python 3.4 에서 추가된 pathlib
모듈의 Path
클래스의 rglob()
메서드를 이용해보자.
>>> from pathlib import Path >>> list(Path("/foo/bar/dir").rglob("*")) [PosixPath('/foo/bar/dir/a'), PosixPath('/foo/bar/dir/a/test.txt'), ...]
PosixPath
라는 새로운 타입이 등장하는데 이름처럼 경로를 표기하는데 적합한 타입이다. 이 타입은 별로 어려울 것 없이 str()
로 문자열로 변환이 되니 익숙한 방법을 사용하면 된다.
어쨌든 이런 식으로 해당 디렉터리 아래의 모든 파일과 디렉터리 목록을 1차원 리스트로 가공된 결과를 얻을 수 있다.
굳이 list()
를 이용해 리스트화를 한 이유는 결과를 바로 보기 위함이다. 보통 이런 경우 generator가 리턴된 것이기 때문에 굳이 list()
로 바로 풀어버릴 필요 없이 바로 for 루프를 돌면서 필요한 처리를 하는 게 성능과 메모리 효율이 더 좋을 것이다.
>>> for p in Path("/Users/seorenn/tmp/a").rglob("*"): ... print(p) ... /foo/bar/dir/a /foo/bar/dir/a/test.txt ...
참고로 rglob()
의 파일 이름 패턴은 이 외의 다양한 패턴을 지원하므로 궁금하다면 매뉴얼을 찾아보자.