14. 파일과 디렉토리 다루기




1 파일 다루기


1-1 파일 목록 얻기

  • os.listdir('경로')
    • 디렉토리 안에 들어 있는 각 파일 목록 반환
In [1]:
import os

print(os.listdir('.'))   # 현재 디렉토리의 파일 목록 얻기
print()

print(os.listdir('../')) # 현재 디렉토리의 부모 디렉토리의 파일 목록 얻기
['assignment2019', 'python10.ipynb', 'python09.ipynb', 'mymath.py', 'assignment-5.ipynb', 'python12.ipynb', 'removeme.txt', 'python16.ipynb', 'supplement-2016-09.ipynb', 'assignment-1.ipynb', 'assignment-3.ipynb', 'python14.ipynb', 'Untitled.ipynb', 'assignment-4.ipynb', 't1.txt', 'python13.ipynb', 'python11.ipynb', 'python08.ipynb', 'pickle.txt', 'assignment-2.ipynb', 'python15.ipynb', '__pycache__', 'python17.ipynb', 'Speech', 'python02.ipynb', 't.txt', 'python19.ipynb', 'module_test.py', 'python04.ipynb', 'python20.ipynb', 'prname.ipynb', 'pickle2.txt', 'python22.ipynb', 'python06.ipynb', 'readme.txt', '.ipynb_checkpoints', 'python18.ipynb', 'python01.ipynb', 'python03.ipynb', 'python23.ipynb', 'output.txt', 'python07.ipynb', 'python05.ipynb', 'prname.py', 'python21.ipynb']

['python10.ipynb', 'music', 'python09.ipynb', 'mymath.py', 'assignment-5.ipynb', 'python12.ipynb', 'Untitled1.ipynb', 'python16.ipynb', 'supplement-2016-09.ipynb', 'assignment-1.ipynb', 'assignment-3.ipynb', 'Untitled3.ipynb', 'python14.ipynb', 'images', 'assignment-4.ipynb', 'python13.ipynb', 'python11.ipynb', 'python08.ipynb', 'The Python Challenge.webloc', 'assignment-2.ipynb', 'turtle_method-3.png', 'turtle_method-2.png', 'python15.ipynb', 'Untitled2.ipynb', 'python3.6', 'python17.ipynb', 'turtle_method-1.png', 'Speech', 'aaa', 'python02.ipynb', 'README.md', 'python19.ipynb', '.gitignore', 'module_test.py', 'python04.ipynb', 'python20.ipynb', 'python22.ipynb', 'files', 'python06.ipynb', 'supplement.ipynb', '.ipynb_checkpoints', 'python18.ipynb', 'python01.ipynb', 'python03.ipynb', '.git', 'python23.ipynb', '과제3-모범답안.ipynb', 'python07.ipynb', 'python05.ipynb', 'turtle_example.png', '범이의 데이터 아키텍처 -- [Python] [개념을 잡아주는 프로그래밍 정석] 4.8 연습문제.webloc', 'mymath.ipynb', 'python21.ipynb']

1-2 파일 종류 알아보기

  • os.path 모듈의 다음 함수들은 파일의 종류를 판단하여 True 또는 False를 반환한다.
    • isfile(filepath)
      • 순수 파일이면 True
    • isdir(filepath)
      • 디렉토리이면 True
    • islink(filepath)
      • 심볼릭링크이면 True
In [15]:
import os
def filetype(fpath):
    print(fpath, ':', end="")
    
    if os.path.isfile(fpath):
        print('Regular file')
        
    if os.path.isdir(fpath):
        print('Directory')

    if os.path.islink(fpath):
        print('Symbolic link')
        
flist = os.listdir('.')
for fname in flist:
    filetype(fname)
assignment2019 :Directory
python10.ipynb :Regular file
python09.ipynb :Regular file
mymath.py :Regular file
assignment-5.ipynb :Regular file
python12.ipynb :Regular file
removeme.txt :Regular file
python16.ipynb :Regular file
supplement-2016-09.ipynb :Regular file
assignment-1.ipynb :Regular file
assignment-3.ipynb :Regular file
python14.ipynb :Regular file
Untitled.ipynb :Regular file
assignment-4.ipynb :Regular file
t1.txt :Regular file
python13.ipynb :Regular file
python11.ipynb :Regular file
python08.ipynb :Regular file
pickle.txt :Regular file
assignment-2.ipynb :Regular file
python15.ipynb :Regular file
__pycache__ :Directory
python17.ipynb :Regular file
Speech :Directory
python02.ipynb :Regular file
t.txt :Regular file
python19.ipynb :Regular file
module_test.py :Regular file
python04.ipynb :Regular file
python20.ipynb :Regular file
prname.ipynb :Regular file
pickle2.txt :Regular file
python22.ipynb :Regular file
python06.ipynb :Regular file
readme.txt :Regular file
.ipynb_checkpoints :Directory
python18.ipynb :Regular file
python01.ipynb :Regular file
python03.ipynb :Regular file
python23.ipynb :Regular file
output.txt :Regular file
python07.ipynb :Regular file
python05.ipynb :Regular file
prname.py :Regular file
python21.ipynb :Regular file

1-3 파일의 허가권

1) 파일의 허가권 알아보기

  • os.access(filepath, mode)
    • mode에 들어갈 값
      • os.F_OK: 파일 자체가 존재하는 것을 테스트
      • os.R_OK: 읽기 권한이 있는 것을 테스트
      • os.W_OK: 쓰기 권한이 있는 것을 테스트
      • os.X_OK: 실행 권한이 있는 것(또는 디렉토리인지)을 테스트
In [16]:
import os
def fileaccess(fpath):
    print(fpath, ':', end="")
    
    if os.access(fpath, os.F_OK): 
        print('Exists - ', end="")
    else: 
        return
    
    if os.access(fpath, os.R_OK): 
        print('R', end="")
        
    if os.access(fpath, os.W_OK): 
        print('W', end="")
        
    if os.access(fpath, os.X_OK): 
        print('X', end="")
    print()
    
flist = os.listdir('.')
for fname in flist:
    fileaccess(fname)
assignment2019 :Exists - RWX
python10.ipynb :Exists - RW
python09.ipynb :Exists - RW
mymath.py :Exists - RW
assignment-5.ipynb :Exists - RW
python12.ipynb :Exists - RW
removeme.txt :Exists - RW
python16.ipynb :Exists - RW
supplement-2016-09.ipynb :Exists - RW
assignment-1.ipynb :Exists - RW
assignment-3.ipynb :Exists - RW
python14.ipynb :Exists - RW
Untitled.ipynb :Exists - RW
assignment-4.ipynb :Exists - RW
t1.txt :Exists - RW
python13.ipynb :Exists - RW
python11.ipynb :Exists - RW
python08.ipynb :Exists - RW
pickle.txt :Exists - RW
assignment-2.ipynb :Exists - RW
python15.ipynb :Exists - RW
__pycache__ :Exists - RWX
python17.ipynb :Exists - RW
Speech :Exists - RWX
python02.ipynb :Exists - RW
t.txt :Exists - RW
python19.ipynb :Exists - RW
module_test.py :Exists - RW
python04.ipynb :Exists - RW
python20.ipynb :Exists - RW
prname.ipynb :Exists - RW
pickle2.txt :Exists - RW
python22.ipynb :Exists - RW
python06.ipynb :Exists - RW
readme.txt :Exists - RW
.ipynb_checkpoints :Exists - RWX
python18.ipynb :Exists - RW
python01.ipynb :Exists - RW
python03.ipynb :Exists - RW
python23.ipynb :Exists - RW
output.txt :Exists - RW
python07.ipynb :Exists - RW
python05.ipynb :Exists - RW
prname.py :Exists - RW
python21.ipynb :Exists - RW

2) 파일의 허가권 변경하기

  • os.chmod(filepath, mode)
In [26]:
os.chmod('output.txt', 0o777) # 리눅스에서의 실행 예

%ls -al output.txt
-rwxrwxrwx  1 yhhan  staff  17 10 27 22:40 output.txt*

1-4 파일 조작하기

1) 파일 이름 변경하기

  • os.rename(old_filepath, new_filepath)
In [51]:
s = """Its power: Python developers typically report 
they are able to develop applications in a half
to a tenth the amount of time it takes them to do
the same work in such languages as C."""

with open('t.txt', 'w') as f:
    f.write(s) # 문자열을 파일에 기록
In [52]:
import os
os.rename('t.txt', 't1.txt')  # t.txt를 t1.txt로 바꾼다
print(os.access('t.txt', os.F_OK))
print(os.access('t1.txt', os.F_OK))
False
True

2) 파일 이동하기

  • os.rename(old_filepath, new_filepath)
In [53]:
os.mkdir('example') 
In [54]:
os.rename('t1.txt', './example/t1.txt') # 현재 작업 디렉토리의 t1.txt를 example에 t1.txt이름으로 옮긴다.
print(os.access('./example/t1.txt', os.F_OK))
True

3) 파일 복사하기

  • shutil 모듈 활용
  • shutil.copyfile(src_filepath, dest_filepath)
In [55]:
import shutil
shutil.copyfile('output.txt', 'output_new.txt')
print(os.access('output_new.txt', os.F_OK))
True

1-5 파일 이름 다루기

1) 상대 경로를 절대 경로로 변환하기 [중요]

  • os.path.abspath(상대경로)
    • 실제 파일 존재와는 무관하게 절대경로로 변경함
In [66]:
import os
print(os.path.abspath('o.txt'))
/Users/yhhan/git/python-e-learning/python3.6/o.txt

2) 주어진 경로의 파일이 존재하는지 확인 [중요]

  • os.path.exists(filepath)
In [67]:
f = '/Users/yhhan/git/python-e-learning/sample.txt'
print(os.path.exists(f))
print(os.path.exists('sample.txt'))
print(os.path.exists('asdf.txt'))
False
False
False

3) 현재/부모 디렉토리를 가리키는 이름 얻기

In [68]:
print(os.curdir) #현재 디렉토리
print(os.pardir) #부모 디렉토리
.
..

4) 디렉토리 분리 문자 얻기

In [69]:
print(os.sep)
/

1-6 경로명 분리하기

1) 경로와 파일명으로 분리

In [70]:
f = '/Users/yhhan/git/python-e-learning/t.txt'

print(os.path.basename(f)) # 파일명만 추출
print(os.path.dirname(f))  # 디렉토리 경로 추출
t.txt
/Users/yhhan/git/python-e-learning

2) 경로명과 파일명을 한번에 분리

In [71]:
print(os.path.split(f))
('/Users/yhhan/git/python-e-learning', 't.txt')

3) MS 윈도우즈에서 드라이브명과 파일 경로명을 분리

In [72]:
print(os.path.splitdrive(f))
('', '/Users/yhhan/git/python-e-learning/t.txt')

4) 확장자 분리

In [73]:
print(os.path.splitext(f))
('/Users/yhhan/git/python-e-learning/t', '.txt')

1-7 경로명 생성하기 [중요]

  • Linux and Mac
In [77]:
path = os.path.join("/", "Users", "yhhan", "git", "python-e-learning", "t.txt")
print(path)
/Users/yhhan/git/python-e-learning/t.txt
  • Windows
In [79]:
path = os.path.join("c:\\", "Users", "yhhan")
print(path)
c:\/Users/yhhan

2 디렉토리 다루기


2-1 디렉토리에 관련된 일반 작업

1) 현재 작업 디렉토리 알아보기

In [24]:
import os
print(os.getcwd())
/Users/yhhan/git/python-e-learning/python3.6

2) 작업 디렉토리 변경하기

In [104]:
path = os.path.join("/", "Users", "yhhan", "Public")
#path = os.path.join("c:\\", "Users", "yhhan", "Public") 

os.chdir(path)
print(os.getcwd())
/Users/yhhan/Public

3) 디렉토리 만들기

In [109]:
import os

os.mkdir('temp')        # 0755 기본 모드(rwxr-xr-x)로 만들어짐
%ls -al temp
# os.mkdir('temp2', 0700) # 0700 모드(rwx------)로 만들어짐

os.mkdir('temp2', 0o700)
os.makedirs('temp2/level1/level2') #0755 기본 모드, 중간에 필요한 디렉토리도 모두생성

print(os.access('/Users/yhhan/Public/temp', os.F_OK))
print(os.access('/Users/yhhan/Public/temp2', os.F_OK))
print(os.access('/Users/yhhan/Public/temp/level1/level2', os.F_OK))
total 0
drwxr-xr-x  2 yhhan  staff   64 10 27 23:39 ./
drwxr-xr-x+ 6 yhhan  staff  192 10 27 23:39 ../
True
True
False
In [110]:
import os

os.mkdir('temp3', 0o700)

path = os.path.join("temp3", "level1", "level2")
os.makedirs(path) #0755 기본 모드, 중간에 필요한 디렉토리도 모두생성

4) 디렉토리 삭제

In [111]:
os.rmdir('temp') #디렉토리에 내용이 없을 때 삭제가능
In [112]:
os.rmdir('temp3') #디렉토리에 다른 파일이 있으면 삭제할 수 없음
---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
<ipython-input-112-4a5a038b13f9> in <module>
----> 1 os.rmdir('temp3') #디렉토리에 다른 파일이 있으면 삭제할 수 없음

OSError: [Errno 66] Directory not empty: 'temp3'

5) 다단계 디렉토리 삭제

  • os.removedirs(filepath)
    • filepath에 지정된 디렉토리들 중 맨 오른쪽 디렉토리 부터 차례차례로 삭제한다.
    • 디렉토리에 다른 파일이 있으면 삭제하기 않고 중단
In [113]:
os.removedirs('temp2/level1/level2')

6) 하위 디렉토리까지 모두 한번에 삭제

  • shutil.rmtree()
    • 파일은 물론 하위 디렉토리까지 모두 한번에 삭제 가능
    • 조심해서 사용해야 함
In [114]:
import os

os.mkdir('temp')        # 0755 기본 모드(rwxr-xr-x)로 만들어짐
os.makedirs('temp/level1/level2') #0755 기본 모드, 중간에 필요한 디렉토리도 모두생성

print(os.access('/Users/yhhan/Public/temp', os.F_OK))
print(os.access('/Users/yhhan/Public/temp/level1/level2', os.F_OK))
True
True
In [115]:
import shutil
shutil.rmtree('temp3')

7) 디렉토리 복사

  • shutil.copytree(src_filepath, dest_filepath)
    • 하위 디렉토리와 파일등을 지니고 있는 디렉토리를 복사
In [118]:
os.mkdir('temp/temp2', 0o700)
shutil.copytree('temp', 'myweb_backup')
Out[118]:
'myweb_backup'

2-2 디렉토리(트리) 탐색하기

  • os.walk(filepath)
    • filepath 부터 시작하여 재귀적으로 모든 하위 디렉토리까지 탐색을 하는 함수
    • 탐색시 발견하는 모든 파일에 대해서는 다음 튜플을 리턴함
      • (dirpath, dirnames, filemnames)
        • dirpath: 탐색하고 있는 디렉토리 경로
        • dirnames: dirpath 안에 존재하는 서브 디렉토리의 리스트
        • filenames: dirpath 안에 존재하는 파일 리스트
  • 아래 예는 현재 디렉토리부터 모든 하위 디렉토리 내에 존재하는 모든 txt 파일을 삭제하는 프로그램
In [130]:
path = os.path.join("/", "Users", "yhhan", "Public")
#path = os.path.join("c:\\", "Users", "yhhan", "Public") 

os.chdir(path)
print(os.getcwd())
/Users/yhhan/Public
In [131]:
if os.path.exists('temp'):
    shutil.rmtree('temp')

path = os.path.join("temp", "level1", "level2")
os.makedirs(path)

with open(os.path.join("temp", "t.txt"), "w") as f:
    f.write("aaa")
    
with open(os.path.join("temp", "level1", "t.txt"), "w") as f:
    f.write("aaa")
    
with open(os.path.join("temp", "level1", "level2", "t.txt"), "w") as f:
    f.write("aaa")

path = os.path.join("temp")
os.chdir(path)
print(os.getcwd())
print()
for path, subdirs, files in os.walk(os.getcwd()):
    for fname in files:
        if fname.endswith('.txt'):
            fullpath = os.path.join(path, fname)
            print('removing', fullpath)
            os.remove(fullpath)

print()
os.chdir("..")
print(os.getcwd())
/Users/yhhan/Public/temp

removing /Users/yhhan/Public/temp/t.txt
removing /Users/yhhan/Public/temp/level1/t.txt
removing /Users/yhhan/Public/temp/level1/level2/t.txt

/Users/yhhan/Public
In [35]:
import os
os.chdir('/Users/yhhan/git/python-e-learning')
print(os.getcwd())
print()
for path, subdirs, files in os.walk(os.getcwd()):
    for fname in files:
        if fname.endswith('.txt'):
            fullpath = os.path.join(path, fname)
            print('removing', fullpath)
            os.remove(fullpath)
/Users/yhhan/git/python-e-learning

removing /Users/yhhan/git/python-e-learning/pickle.txt
removing /Users/yhhan/git/python-e-learning/pickle2.txt
removing /Users/yhhan/git/python-e-learning/readme.txt
removing /Users/yhhan/git/python-e-learning/removeme.txt
removing /Users/yhhan/git/python-e-learning/sample.txt
removing /Users/yhhan/git/python-e-learning/sample_new.txt
removing /Users/yhhan/git/python-e-learning/t.txt
removing /Users/yhhan/git/python-e-learning/t1.txt
removing /Users/yhhan/git/python-e-learning/t2.txt
removing /Users/yhhan/git/python-e-learning/example/t1.txt
removing /Users/yhhan/git/python-e-learning/python3.6/output.txt
removing /Users/yhhan/git/python-e-learning/python3.6/sample.txt
removing /Users/yhhan/git/python-e-learning/python3.6/sample_new.txt
removing /Users/yhhan/git/python-e-learning/python3.6/t_new.txt
removing /Users/yhhan/git/python-e-learning/python3.6/example/t1.txt

참고 문헌: 파이썬(열혈강의)(개정판 VER.2), 이강성, FreeLec, 2005년 8월 29일