파일시스템

1. os.path

- 파일 경로를 생성, 수정, 파일 정보를 쉽게 다룰 수 있게 해주는 모듈

- from os.path import *를 명시하여 모듈 임포트 후 진행


1) os.path.abspath(path)

- 현재 경로를 Prefix로 하여 입력받은 경로를 절대경로로 바꿔서 반환

- 작성하는 소스코드가 위치한 현재 경로: /Users/eunguru/Source/Python/FileSystem

print("abspath('tmp'):", abspath('tmp'))

abspath('tmp'): /Users/eunguru/Source/Python/FileSystem/src/tmp

2) os.path.basename(path)

- 입력받은 경로의 기본 이름(base name)을 반환

- abspath() 함수와 반대되는 기능 수행

윈도우 경로 표기 주의 할 것(윈도우에서 실습 시 \\으로 경로 구분, Mac에서 실습시 //로 구분)

print("basename('C:\\Python30\\tmp'):", basename('C:\\Python30\\tmp'))

basename('C:\Python30\tmp'): C:\Python30\tmp


print("basename('C://Python30//tmp'):", basename('C://Python30//tmp'))

basename('C://Python30//tmp'): tmp


print("basename('/Users/eunguru/Source/Python/FileSystem'):", 

      basename('/Users/eunguru/Source/Python/FileSystem'))

basename('/Users/eunguru/Source/Python/FileSystem'): FileSystem


print("basename('/Users/eunguru/Source/Python/FileSystem/FileSystem.py'):", 

      basename('/Users/eunguru/Source/Python/FileSystem/FileSystem.py'))

basename('/Users/eunguru/Source/Python/FileSystem/FileSystem.py'): FileSystem.py

3) os.path.commonprefix(path_list)

- 입력 받은 path_list로부터 공통적인 prefix를 추출해서 반환

print(commonprefix(['C://python30//Lib', 'C://python30//Tools', 'C://python30']))

C://python30

- 문자열 연산에 의한 것으로 잘못된 경로가 반환될 수 있음

print(commonprefix(['C://python25//Tools', 'C://python26//Tools']))

C://python2

4) os.path.dirname(path)

- 입력 받은 파일/디렉토리의 경로 반환,  전체 경로에서 기본 이름(basename)을 제외한 경로 반환

print("dirname('C://Python30//tmp//test.txt'):", dirname('C://Python30//tmp//test.txt'))

dirname('C://Python30//tmp//test.txt'): C://Python30//tmp

print("dirname('C://Python30//tmp'):", dirname('C://Python30//tmp'))

dirname('C://Python30//tmp'): C://Python30

5) os.path.exists(path)

- 입력받은 경로가 존재하면 True, 존재하지 않은 경우 False 반환

print("exists('C://Python30//tmp'):", exists('C://Python30//tmp'))

exists('C://Python30//tmp'): False


print("exists('/Users/eunguru/Source/Python/FileSystem'):",

      exists('/Users/eunguru/Source/Python/FileSystem'))

exists('/Users/eunguru/Source/Python/FileSystem'): True

- 리눅스와 같은 OS에서는 파일이나 디렉토리가 존재하지만 읽기 권한이 없는 경우에도 False를 반환 할 수 있음

(테스트를 위해 임의로 권한이 없는 빈 파일 생성후 테스트 했으나 True로 출력, False로 반환 되는 경우도 있다고 하니 참고용으로만 알아둘 것.)

print("exists('/Users/eunguru/Source/Python/FileSystem/TestFile'):",

      exists('/Users/eunguru/Source/Python/FileSystem/TestFile'))

exists('/Users/eunguru/Source/Python/FileSystem/TestFile'): True

6) os.path.expanduser(path)

- 입력받은 경로안의 "~"을 현재 사용자 홈 디렉토리의 절대경로로 대체 (사용환경에 따라 결과 다름)

- 홈 디렉토리 경로 확인

a. "~": 입력 경로에 홈 디렉토리 경로를 포함하여 절대 경로로 대체

print("expanduser('~//test'):", expanduser('~//test'))

expanduser('~//test'): /Users/eunguru//test

b. "~<사용자 명>: 원하는 사용자 경로로 대체 (Mac에서는 동작하지 않음, 윈도우에서는 동작)


7) os.path.expandvars(path)

- path안에 환경 변수가 있다면 확장함.

- 확경변수는 os.environ에 정의 된 것을 참조함

print("expandvars('$HOME/tmp'):", expandvars('$HOME/tmp'))

expandvars('$HOME/tmp'): /Users/eunguru/tmp

8) os.path.getatime(path)

- 입력 받은 경로에 대한 최근 접근 시간을 반환

- 반환되는 값은 epoch(1970년 1월 1일)이후 초단위로 반환

print("getatime('/Users/eunguru/Source/Python/FileSystem'):", 

      getatime('/Users/eunguru/Source/Python/FileSystem'))

getatime('/Users/eunguru/Source/Python/FileSystem'): 1435665410.0

- 파일이 없거나 권한이 없는 경우 os.error 예외가 발생됨

(권한이 없는 경우는 예외 발생하지 않음, 파일이 없는 경우 FileNotFoundError 예외 발생됨)

# 파일의 권한이 없는 경우 예외가 발생되지 않음 

print("getatime('/Users/eunguru/Source/Python/FileSystem/TestFile'):", 

      getatime('/Users/eunguru/Source/Python/FileSystem/TestFile'))

getatime('/Users/eunguru/Source/Python/FileSystem/TestFile'): 1435665449.0


print("getatime('/Users/eunguru/Source/Python/FileSystem/TestFile1'):", 

      getatime('/Users/eunguru/Source/Python/FileSystem/TestFile1'))

Traceback (most recent call last):

  File "/Users/eunguru/Source/Python/FileSystem/src/FileSystem.py", line 40, in <module>

    getatime('/Users/eunguru/Source/Python/FileSystem/TestFile1'))

  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/genericpath.py", line 60, in getatime

    return os.stat(filename).st_atime

FileNotFoundError: [Errno 2] No such file or directory: '/Users/eunguru/Source/Python/FileSystem/TestFile1'

* 참고: getatime()의 반환 값을 읽을 수 있는 형식으로 보려면 아래와 같이 코드로 작성

import time

print(time.gmtime(getatime('/Users/eunguru/Source/Python/FileSystem')))

time.struct_time(tm_year=2015, tm_mon=6, tm_mday=30, tm_hour=11, tm_min=56, tm_sec=50, tm_wday=1, tm_yday=181, tm_isdst=0)

9) os.path.getmtime(path)

- 입력받은 경로에 대한 최근 변경 시간을 반환

- 파일이 없어나 권한이 없는 경우에는 os.error 예외 발생

print("getmtime('/Users/eunguru/Source/Python/FileSystem'):", 

      getmtime('/Users/eunguru/Source/Python/FileSystem'))

getmtime('/Users/eunguru/Source/Python/FileSystem'): 1435665449.0

10) os.path.getctime(path)

- 입력받은 경로에 대한 생성 시간을 반환

- 유닉스와 같은 운영체제에서는 생성시간이 아닌 최근 변경 시간을 반환할 수 있음

- 파일이 없어나 권한이 없는 경우에는 os.error 예외 발생

print("getctime('/Users/eunguru/Source/Python/FileSystem'):", 

      getctime('/Users/eunguru/Source/Python/FileSystem'))


getctime('/Users/eunguru/Source/Python/FileSystem'): 1435665449.0


11) os.path.getsize(path)

- 입력받은 경로에 대한 바이트 단위의 파일 크기를 반환

- 파일이 없어나 권한이 없는 경우에는 os.error 예외 발생

print("getsize('/Users/eunguru/Source/Python/FileSystem'):", 

      getsize('/Users/eunguru/Source/Python/FileSystem'))

getsize('/Users/eunguru/Source/Python/FileSystem'): 204


12) os.path.isabs(path)

- 경로가 절대경로이면 True를 반환하고 그 외의 경우에는 False를 반환

- 실제 해당 경로를 검사하지 않으며, 입력 받은 문자열을 가지고 판단함

print("isabs('/Users/eunguru/Source/Python/FileSystem'):", 

    isabs('/Users/eunguru/Source/Python/FileSystem'))

isabs('/Users/eunguru/Source/Python/FileSystem'): True


print("isabs('./FileSystem'):", isabs('./FileSystem'))

isabs('./FileSystem'): False


12) os.path.isfile(path)

- 경로가 파일이면 True를 반환하고 그 외의 경우에는 False를 반환

print("isfile('/Users/eunguru/Source/Python/FileSystem'):", 

    isfile('/Users/eunguru/Source/Python/FileSystem'))

isfile('/Users/eunguru/Source/Python/FileSystem'): False


print("isfile('/Users/eunguru/Source/Python/FileSystem/TestFile'):", 

    isfile('/Users/eunguru/Source/Python/FileSystem/TestFile'))

isfile('/Users/eunguru/Source/Python/FileSystem/TestFile'): True

- 해당 경로가 존재하지 않는 경우는 False를 반환

print("isfile('/Users/eunguru/Source/Python/FileSystem/TestFile1'):", 

    isfile('/Users/eunguru/Source/Python/FileSystem/TestFile1'))
isfile('/Users/eunguru/Source/Python/FileSystem/TestFile1'): False

13) os.path.isdir(path)

- 경로가 디렉토리이면 True를 반환하고 그 외의 경우에는 False를 반환

print("isdir('/Users/eunguru/Source/Python/FileSystem'):", 

    isdir('/Users/eunguru/Source/Python/FileSystem'))

isdir('/Users/eunguru/Source/Python/FileSystem'): True


print("isdir('/Users/eunguru/Source/Python/FileSystem/TestFile'):", 

    isdir('/Users/eunguru/Source/Python/FileSystem/TestFile'))

isdir('/Users/eunguru/Source/Python/FileSystem/TestFile'): False

- 해당 경로가 존재하지 않는 경우는 False를 반환

print("isdir('/Users/eunguru/Source/Python/FileSystem/TestFile1'):", 

    isdir('/Users/eunguru/Source/Python/FileSystem/TestFile1'))

isdir('/Users/eunguru/Source/Python/FileSystem/TestFile1'): False

14) os.path.join(path1[, path2[, ...]])

- 해당 os 형식에 맞도록 입력받은 경로를 연결, 입력 중간에 절대경로가 나오면 이전에 취합된 경로는 제거하고 다시 연결

print("join('/User/eunguru', 'Source', 'Python'):", 

      join('/User/eunguru', 'Source', 'Python'))

print("join('/User/eunguru', 'Source', '/Python/FileSystem/TestFile'):", 

      join('/User/eunguru', 'Source', '/Python/FileSystem/TestFile'))

join('/User/eunguru', 'Source', 'Python'): /User/eunguru/Source/Python

join('/User/eunguru', 'Source', '/Python/FileSystem/TestFile'): /Python/FileSystem/TestFile

- 윈도우에서 실행


15) os.path.normacase(path)

- 해당 os에 맞도록 입력받은 경로의 문자열을 정규화함

- 윈도우와 같은 경우 소문자로 변경하고 '/'를 '\\'로 변경함


16) os.path.normpath(path)

- 입력받은 경로를 정규화 함, 현재 디렉토리(".")나 상위 디렉토리("..")와 같은 구분자를 최대한 삭제

- 앞에 있는 .나 ..는 삭제되지 않음

print("normpath('../Users/./eunguru/../Source')):", 

      normpath('../Users/./eunguru/../Source'))

normpath('../Users/./eunguru/../Source')): ../Users/Source

17) os.path.split(path)

- 입력받은 경로를 디렉토리 부분과 파일 부분(basename)으로 나눔

- 단순한 문자열 연산이므로 실제 파일의 존재 여부는 확인하지 않음

print("split('/Users/eunguru/Source/Python/FileSystem'):", 

      split('/Users/eunguru/Source/Python/FileSystem'))

split('/Users/eunguru/Source/Python/FileSystem'): ('/Users/eunguru/Source/Python', 'FileSystem')

18) os.path.splitdrive(path)

- 입력받은 경로를 드라이브 부분과 나머지 부분으로 나눔 (윈도우에서 사용하는 것이 적합한 것 같음)

- 단순한 문자열 연산이므로 실제 파일의 존재 여부는 확인하지 않음

print("splitdrive('/Users/eunguru/Source/Python/FileSystem'):", 

      splitdrive('/Users/eunguru/Source/Python/FileSystem'))

splitdrive('/Users/eunguru/Source/Python/FileSystem'): ('', '/Users/eunguru/Source/Python/FileSystem')


19) os.path.splitext(path)

- 입력받은 경로를 확장자 부분과 그 외의 부분으로 나눔

- 단순한 문자열 연산이므로 실제 파일의 존재 여부는 확인하지 않음

print("splitext('/Users/eunguru/Source/Python/FileSystem/FileSystem.py'):", 

      splitext('/Users/eunguru/Source/Python/FileSystem/FileSystem.py'))

splitext('/Users/eunguru/Source/Python/FileSystem/FileSystem.py'): ('/Users/eunguru/Source/Python/FileSystem/FileSystem', '.py')


2. glob

- glob 모듈은 윈도우의 dir 명령어나 리눅스의 ls와 유사한 기능을 제공


1) glob.glob(path)

- glob()함수는 경로에 대응되는 모든 파일 및 디렉터리의 리스트를 반환

- 경로를 따로 주지 않으면 현재 디렉토리 기준으로 대응되는 리스트를 반환

- *, ?, [,] 같은 문자 표현도 가능

- 경로를 주는 방식에 따라 절대경로나 상대경로로 출력

import glob

print("glob.glob('File*'):", glob.glob('File*'))

glob.glob('File*'): ['FileSystem.py']


print("glob.glob('../Test/TestFile?.*'):", glob.glob('../Test/TestFile?.*'))

glob.glob('../Test/TestFile?.*'): ['../Test/TestFile1.txt', '../Test/TestFile2.txt', '../Test/TestFile3.txt', '../Test/TestFilea.txt']


print("glob.glob('../Test/TestFile[0-9].*'):", glob.glob('../Test/TestFile[0-9].*'))

glob.glob('../Test/TestFile[0-9].*'): ['../Test/TestFile1.txt', '../Test/TestFile2.txt', '../Test/TestFile3.txt']


print("glob.glob('../Test/TestFile[a-z].*'):", glob.glob('../Test/TestFile[a-z].*'))

glob.glob('../Test/TestFile[a-z].*'): ['../Test/TestFilea.txt']


print("glob.glob('/Users/eunguru/Source/Python/FileSystem/Test/Test*'):", 

      glob.glob('/Users/eunguru/Source/Python/FileSystem/Test/Test*'))

glob.glob('/Users/eunguru/Source/Python/FileSystem/Test/Test*'): ['/Users/eunguru/Source/Python/FileSystem/Test/TestFile1.txt', '/Users/eunguru/Source/Python/FileSystem/Test/TestFile2.txt', '/Users/eunguru/Source/Python/FileSystem/Test/TestFile3.txt', '/Users/eunguru/Source/Python/FileSystem/Test/TestFilea.txt']


print("glob.glob(abspath('../Test') + '/*.txt'):", glob.glob(abspath('../Test') + '/*.txt'))

glob.glob(abspath('../Test') + '/*.txt'): ['/Users/eunguru/Source/Python/FileSystem/Test/TestFile1.txt', '/Users/eunguru/Source/Python/FileSystem/Test/TestFile2.txt', '/Users/eunguru/Source/Python/FileSystem/Test/TestFile3.txt', '/Users/eunguru/Source/Python/FileSystem/Test/TestFilea.txt']

2) glob.iglob(path)

- glob와 동일한 동작을 수행, 리스트로 결과를 반환하는 것이 아니라 이터레이터를 반환

- 한번에 모든 결과를 리스트에 담지 않으므로, 결과가 매우 많은 경우 유용하게 사용

- glob()와 iglob()의 리턴 타입 확인

# glob()와 iglob()의 return type 확인 

print("type(glob.glob('File*')):", type(glob.glob('File*')))

print("type(glob.iglob('File*')):", type(glob.iglob('File*')))

type(glob.glob('File*')): <class 'list'>

type(glob.iglob('File*')): <class 'generator'>

- iglob() 예제

print("glob.iglob('../Test/*'):", glob.iglob('../Test/*'))

for i in glob.iglob('../Test/*'):

    print("-", i)


glob.iglob('../Test/*'): <generator object iglob at 0x1019a8630>

- ../Test/TestFile1.txt <class 'str'>

- ../Test/TestFile2.txt <class 'str'>

- ../Test/TestFile3.txt <class 'str'>

- ../Test/TestFilea.txt <class 'str'>


3. Tree

- 하위 디렉토리 구조를 보여주는 툴


1) tree 실행 결과 예제

a. 윈도우 tree 

- 실행시 아래와 같이 결과 출력


b. 리눅스 tree

- 명령어 파일이 존재하지 않아서 패키지 관리자를 통해 설치 후 tree 명령어 실행


c. 맥 tree

- 명령어 파일이 존재하지 않아서 별도로 설치해야 되나 아직 찾아보지 않음(추후 방법 따로 정리..)

+ 추가

- 맥의 경우 파인더에서 해당 폴더를 텍스트 에디터에 끌어다 놓으면 트리형식으로 출력됨


2) os.path와 glob의 일부 기능을 이용하여 tree와 비슷한 기능을 수행하는 예제 작성 가능

- 경로를 입력하면 그 안의 모든 디렉토리와 파일을 출력해주는 함수 작성해야함

- 함수 내부에서 파일인 경우에는 파일이름 출력, 디렉토리인 경우 디렉토리명을 출력

- 출력시 띄어쓰기 조절하여 출력


a. 소스 코드 작성

- 책의 소스 코드에서 변경

- 소스위치경로: /Users/eunguru/Source/Python/FileSystem/src

- 재귀함수 호출을 통해 입력된 경로의 하위 디렉토리의 파일, 디렉토리 또한 출력되도록 변경(소스코드 24번째줄 참조)

'''
Created on 2015. 7. 1.

@author: eunguru
'''
import glob, os.path

ndir = nfile = 0    # 합계 출력을 위한 변수 

def traverse(dir, depth):
    global ndir, nfile
    
    for obj in glob.glob(dir + '/*'):
        if depth == 0:
            prefix = '|--'
        else:
            prefix = '|' + '    ' * depth + '|--'
        
        # 디렉토리인 경우 
        if os.path.isdir(obj):
            ndir += 1
            print(prefix + os.path.basename(obj))
            # 하위 디렉토리의 파일, 디렉토리 출력을 위해 재귀함수 호출 
            traverse(obj, depth+1)
        
        # 파일인 경우 
        elif os.path.isfile(obj):
            nfile += 1
            print(prefix + os.path.basename(obj))
        
        # 그 외의 경우 처리 
        else:
            print(prefix + 'uknown object :', obj)

if __name__ == '__main__':
    path = '..' # 경로 지정 
    print('path:', os.path.abspath(path))
    
    traverse(path, 0)
    # 전체 합계 출력 
    print('\n', ndir, 'directories,', nfile, 'files')


b. 실행 결과

- 재귀함수 호출부분 추가 전 실행결과

path: /Users/eunguru/Source/Python/FileSystem

|--src

|--Test

|--TestFile


 2 directories, 1 files

- 재귀함수 호출부분 추가 후 실행결과 (3-1)-b,c 와 결과 동일함)

path: /Users/eunguru/Source/Python/FileSystem

|--src

|    |--FileSystem.py

|    |--Tree.py

|--Test

|    |--SubTest

|        |--SubTestFile1

|        |--SubTestFile2

|        |--SubTestFile3

|    |--TestFile1.txt

|    |--TestFile2.txt

|    |--TestFile3.txt

|    |--TestFilea.txt

|--TestFile


 3 directories, 10 files


'컴&프로그래밍 > Python' 카테고리의 다른 글

14. 데이터베이스 사용  (0) 2015.08.03
9. C/C++와 연동  (3) 2015.03.14
8. 입출력  (0) 2015.01.14
7. 예외처리  (0) 2015.01.02
6. 모듈  (0) 2014.12.29
Mac OS X Yosemite에서 PyCharm 설치 후 실행  (0) 2014.12.27
5. 클래스  (0) 2014.12.20
4. 제어  (0) 2014.12.19
Google Python Tutorial - Basic Python Exercises #2 List  (0) 2014.12.11