이번 포스팅에서는 유닉스 스타일로 Python의 파일 경로와 파일명 패턴 매칭을 통해 찾아주는 glob, fnmatch 모듈에 대해서 알아보겠습니다. 

 

(1) glob: 유닉스 스타일 경로명 패턴 확장 (Unix style pathname pattern expansion)

(2) fnmatch: 유닉스 스타일 파일명 패턴 매칭 (Unix style filename pattern matching)

 

python glob, fnmatch module

 

 

(1) glob: 유닉스 스타일 경로명 패턴 확장 (Unix style pathname pattern expansion)

 

Python의 glob 모듈은 Unix shell에서 사용되는 규칙에 따라 지정된 패턴과 일치하는 모든 경로 이름을 찾아주며, 결과는 임의의 순서로 반환합니다. 

 

간단한 예를 들어서 설명해보겠습니다. 아래와 같은 파일경로의 계층으로 여러개의 파일이 있습니다. 

 

- data > glob 폴더내 'glob.ipynb' 파일, train 하위 폴더, test 하위 폴더

- data > glob > train 폴더 내 '1.txt', '2.txt', '1001.txt', '1002.txt', 'a.txt', 'b.txt', 'cat.jpeg'

- data > glob > test 폴더 내 '4.txt', '5.txt', 'd.txt', e.txt'

파일경로, 파일명 예시

 

 

(1-1) glob.glob('./*'): 현재 폴더의 폴더와 파일 경로 가져오기

 

import glob

## 현재 폴더의 폴더와 파일 경로
glob.glob('./*')

# ['./test', './glob.ipynb', './train']

 

 

(1-2) glob.glob(./foldername/*'): 특정 폴더 내 모든 파일 경로 가져오기

 

## ''./train' 경로의 모든 파일 경로
glob.glob('./train/*')

# ['./train/cat.jpeg',
#  './train/b.txt',
#  './train/a.txt',
#  './train/2.txt',
#  './train/1002.txt',
#  './train/1.txt',
#  './train/1001.txt']

 

 

(1-3) glob: 특정 폴더 내 특정 파일이름으로 끝나는 모든 파일 경로 가져오기 

 

예 1) '.txt' 로 끝나는 파일 경로

## '.txt' 로 끝나는 파일 경로
glob.glob('./train/*.txt')

# ['./train/b.txt',
#  './train/a.txt',
#  './train/2.txt',
#  './train/1002.txt',
#  './train/1.txt',
#  './train/1001.txt']

 

 

예 2) '.jpeg' 로 끝나는 파일 경로 

## '.jpeg' 로 끝나는 파일 경로
glob.glob('./train/*.jpeg')

# ['./train/cat.jpeg']

 

 

(1-4) glob.glob([0-9]*): 0~9 숫자로 시작하는 파일 경로 가져오기

 

## 0~9 숫자로 시작하는 파일 경로
glob.glob('./train/[0-9]*')

# ['./train/2.txt', 
#  './train/1002.txt', 
#  './train/1.txt', 
#  './train/1001.txt']

 

 

(1-5) glob.glob('./**/*', recursive=True)
  : 현재 폴더에 있는 폴더와 파일, 하위 폴더 내 모든 파일 경로 재귀적으로 가져오기

 

## ''**/*' 와 recursive=True : 현재 폴더에 있는 폴더와 파일, 하위 폴더 내 경로 재귀적으로 가져오기 
glob.glob('./**/*', recursive=True)

# ['./test',
#  './glob.ipynb',
#  './train',
#  './test/5.txt',
#  './test/4.txt',
#  './test/e.txt',
#  './test/d.txt',
#  './train/cat.jpeg',
#  './train/b.txt',
#  './train/a.txt',
#  './train/2.txt',
#  './train/1002.txt',
#  './train/1.txt',
#  './train/1001.txt']

 

 

(1-6) glob.glob('./**/*/', recursive=True): 현재 폴더에 있는 폴더 경로만 가져오기

 

## 제일 마지막에 '/' 추가: 폴더만
glob.glob('./**/*/', recursive=True)

# ['./test/', './train/']

 

 

(1-7) 디렉토리(<DIR>)와 파일(<FILE>) 구분자 추가해서 프린트 하기

 

import glob
from os.path import isdir

for x in glob.glob('./**/*', recursive=True):
    if isdir(x):
        print('<DIR> ', x) # 디렉토리
    else:
        print('<FILE>', x) # 파일
        
# <DIR>  ./test
# <FILE> ./glob.ipynb
# <DIR>  ./train
# <FILE> ./test/5.txt
# <FILE> ./test/4.txt
# <FILE> ./test/e.txt
# <FILE> ./test/d.txt
# <FILE> ./train/cat.jpeg
# <FILE> ./train/b.txt
# <FILE> ./train/a.txt
# <FILE> ./train/2.txt
# <FILE> ./train/1002.txt
# <FILE> ./train/1.txt
# <FILE> ./train/1001.txt

 

 

(1-8) 재귀하면서(recursive=True) 모든 폴더 내 파일 이름만 리스트로 가져오기

 

## 모든 폴더 내 파일 이름만 가져오기
import os

fnames = [
    os.path.basename(x) # 파일 이름
    for x in glob.glob('./**/*', recursive=True) # 재귀하면서 폴더&파일경로
    if not isdir(x) # 폴더 제외
]

print(fnames)

# ['glob.ipynb', 
#  '5.txt', 
#  '4.txt', 
#  'e.txt', 
#  'd.txt', 
#  'cat.jpeg', 
#  'b.txt', 
#  'a.txt', 
#  '2.txt', 
#  '1002.txt', 
#  '1.txt', 
#  '1001.txt']

 

 

(1-9) 재귀 대신 매뉴얼하게 모든 폴더를 지정해주어서 파일 이름만 리스트로 가져오기

 : 위의 (1-8) 재귀문과 결과 동일. 하위 폴더 개수가 많을 수록 (1-9) 수작업 코드 복잡해지고, 자동화에 제약 있음. 

 

## 파일 이름만 가져오기 : os.listdir() 이용해서
## 재귀 대신 매뉴얼하게 모든 폴더를 써줘야 함
import os

os.listdir('./') + os.listdir('./train/') + os.listdir('./test/')

# ['.DS_Store',
#  'test',
#  'glob.ipynb',
#  'train',
#  '.ipynb_checkpoints',
#  'cat.jpeg',
#  '.DS_Store',
#  'b.txt',
#  'a.txt',
#  '2.txt',
#  '1002.txt',
#  '1.txt',
#  '1001.txt',
#  '.DS_Store',
#  '5.txt',
#  '4.txt',
#  'e.txt',
#  'd.txt']

 

 

(1-10) 반복자(iterator) 반환하여 for loop 순환문에 사용하기

 

# glob.iglob(): 반복자(iterator) 반환
path_iterator = glob.iglob('./train/**.txt')

for path in path_iterator:
    print(path)
    
# ./train/b.txt
# ./train/a.txt
# ./train/2.txt
# ./train/1002.txt
# ./train/1.txt
# ./train/1001.txt

 

 

 

(2) fnmatch: 유닉스 스타일 파일명 패턴 매칭 (Unix style filename pattern matching)

 

fnmatch.fnmatch(filename, pattern) 메소드는 faiename 문자열이 pattern 문자열과 일치하는지를 검사하여, True나 False 를 반환합니다. 패턴 매칭하는 구문은 아래와 같습니다. 

 

    [seq] : seq 의 모든 문자와 일치합니다. 

    * : 모든 것과 일치합니다. 

 

 

(2-1) 특정 폴더 내 숫자로 시작('[0-9]*')하는 모든 파일 이름 가져오기

 

## filename 문자열이 pattern 문자열과 일치하는지를 검사하여, True 나 False를 반환합니다.
import fnmatch
import os

for file in os.listdir('./train'):
    # [seq]  seq의 모든 문자와 일치합니다.
    # *      모든 것과 일치합니다
    if fnmatch.fnmatch(file, '[0-9]*'):
        print(file)
        
# 2.txt
# 1002.txt
# 1.txt
# 1001.txt

 

 

(2-2) 특정 폴더 내 문자로 시작([!0-9]*')하는 모든 파일 이름 가져오기

 

for file in os.listdir('./train'):
    # [!seq] seq에 없는 모든 문자와 일치합니다
    if fnmatch.fnmatch(file, '[!0-9]*'):
        print(file)
        
# cat.jpeg
# b.txt
# a.txt

 

 

(2-3) 특정 폴더 내 특정 문자열로 끝나는 파일 이름 가져오기

 

for file in os.listdir('./train'):
    # *      모든 것과 일치합니다
    if fnmatch.fnmatch(file, '*.jpeg'):
        print(file)
        
# cat.jpeg

 

 

(2-4) 특정 폴더 내 모든 단일 문자('?')와 일치하는 파일 이름 가져오기

 

for file in os.listdir('./train'):
    # ?      모든 단일 문자와 일치합니다
    if fnmatch.fnmatch(file, '?.txt'):
        print(file)
        
# b.txt
# a.txt
# 2.txt
# 1.txt

 

 

(2-5) 특정 폴더 내 모든 파일 이름 가져오기

 

for file in os.listdir('./train'):
    # *      모든 것과 일치합니다
    if fnmatch.fnmatch(file, '*.txt'):
        print(file)
        
# b.txt
# a.txt
# 2.txt
# 1002.txt
# 1.txt
# 1001.txt

 

 

 

[Reference]

- glob module: https://docs.python.org/3/library/glob.html

- fnmatch module: https://docs.python.org/3/library/fnmatch.html#module-fnmatch

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요! :-)

 

728x90
반응형
Posted by Rfriend
,