본문 바로가기

Linux

[Shell] 쉘프로그래밍으로 초간단 자동 압축해제 프로그램 만들기

반응형

우리 연구실은 태양광 관련 연구를 지속하고 있기 때문에 기상 데이터에도 관심이 많다. 의미가 있는 데이터는 어떻게든 다른 데이터와 연관시켜서 분석할 필요가 있기 때문에 닥치는대로 모으고 있다.

최근에는 기상청의 종관기상관측(ASOS, Automated Synoptic Observing System) 데이터를 모으기 위해 기상자료개방포털에서 데이터를 받아본 후 자료형태와 항목 종류 등을 관찰하고 있었다. 그런데 파일셋 조회에서 자료형태, 기간, 지점명을 선택하고 조회를 하면 하나의 지점에 대한 1개월치 데이터를 하나씩 보여주기 때문에 일일이 다운로드를 눌러줘야 하는 불-편함이 있었다. 방대한 데이터를 모으기 위해서는 상당히 비효율적인 구조였다. 이런 사이트를 만나면 누구보다도 불-편해하는 나였기에 자동화 프로그램을 만들고 싶었지만 아직은 데이터에 대한 관찰단계였고 자동화하려면 기상자료개방포털 홈페이지에 대한 좀 더 면밀한 분석이 필요해서 일단은 좀 진정하고 필요한 만큼만 수동으로 받기로 했다.

그렇게 83개를 불-편하게 수동으로 받았는데 또 하나의 관문이 있었다... 바로 다운받은 파일 모두 압축파일이었던 것이다! 이걸 본 순간 앞이 까마득하였고 이 때부터는 정말 불-편 했다. 그렇게 고민하던 중, 현재 디렉토리의 파일들 압축 해제는 자동화 할 수 있을것 같다는 생각이 들었다. 그래서 초간단으로 만들었다. 뭐 이런거까지 포스팅 해야하나 싶을정도로 간단하지만 누군가 필요할수도 있으므로 올려본다.

 

1. 고찰

1.1 문제점 분석

현재 봉착한 문제는 83개의 압축파일을 모두 해제해야 하는데 수동으로 하나씩 압축해제하기 너무 불-편하다는 것이다.

 

1.2 해결 방안

83개의 압축파일들을 보고 딱 처음 든 생각은 이것이다.

"디렉토리 내의 모든 파일을 순회하면서 하나씩 압축 해제 명령을 때리면 되지 않을까?"

 

1.3 해결 방안을 실현하기 위한 기능 정의

1.3.1 디렉토리 내 모든 파일 순회

파이썬에 친숙한 나지만 파이썬 프로젝트 생성, 패키지 설치 등등 마저도 귀찮은 상태이므로 (이 정도면 포스팅 작성하는 것도 귀찮을텐데...) 쉘에서 사용가능한 압축 해제 명령이 있다면, 쉘 스크립트 상에서 디렉토리 내의 모든 파일을 순회하면서 압축명령을 수행하면 가능하리라고 생각했다.

단순하게 생각했을 때 파이썬의 for loop, 자바의 foreach 등 어떤 집합에서 요소를 하나씩 꺼내 쓰는 식의 loop 구조가 쉘스크립트에도 있을 것이라는 확신이 있었는데 역시나 그랬다. 쉘스크립트에서의 for loop는 파이썬의 그것과 유사했다.

https://www.cyberciti.biz/faq/bash-for-loop/

 

Bash For Loop Examples - nixCraft

Explains how to use a Bash for loop control flow statement on Linux / UNIX / *BSD / macOS bash shell with various programming examples.

www.cyberciti.biz

1.3.2 압축해제

기상자료개방포털의 파일셋조회에서 제공하는 압축파일의 확장자는 .zip이다. 우분투 리눅스에서는 zip파일 압축과 압축 해제 등의 기능을 지원하는 unzip 명령이 있다. unzip으로 압축 해제하는 방법은 매우 간단하다.

https://linux.die.net/man/1/unzip

 

unzip(1) - Linux man page

unzip(1) - Linux man page Name unzip - list, test and extract compressed files in a ZIP archive Synopsis unzip [-Z] [-cflptTuvz[abjnoqsCDKLMUVWX$/:^]] file[.zip] [file(s) ...] [-x xfile(s) ...] [-d exdir] Description unzip will list, test, or extract files

linux.die.net

2. 구현

이제 만들고자 하는 프로그램이 어느 정도 윤곽이 잡혔으므로 구현을 해보자.

쉘프로그래밍에서 디렉토리 내의 파일을 순회하는 방법은 매우 간단하다. 

#!/bin/bash
dir=...(디렉토리명)...

for file in $dir/*
do
    ...(do something)...
done

이게 끝.

설명 좀더 하면 dir에 정의된 디렉토리 내에 파일 하나씩 읽어서 file로 할당을 하면 do~done문 내에서 file은 파일 하나의 이름이 된다.

 

그렇다면 여기 do~done문 내에서 압축해제를 때리면 되겠지? 그렇다.

 

#!/bin/bash
dir=...(디렉토리명)...

for file in $dir/*
do
    echo "$file"
    unzip $file
done

zip파일의 압축을 해제하는 명령은 "unzip 파일명"이다. 정말 간단하다.

echo는 출력 명령이다. 현재 무슨 파일을 읽으려는지 이름을 출력해준다.

 

$ ll
total 39736
drwxrwxr-x 1 witlab witlab   7328  7월  8 14:46 ./
drwxr-xr-x 1 witlab witlab   1126  7월  8 11:19 ../
-rw------- 1 witlab witlab 492351  7월  5 17:24 SURFACE_ASOS_129_MI_2017-01_2017-01_2017.zip
...(생략)...
-rw-rw-r-- 1 witlab witlab     99  7월  8 14:46 unzip_all.sh

쉘스크립트는 완성되었는데 아직은 텍스트파일 형태로 인식이 되므로 이 파일을 실행가능한(executable) 파일로 만들어줘야한다.

$ chmod 755 unzip_all.sh
$ ll
total 39736
drwxrwxr-x 1 witlab witlab   7328  7월  8 14:46 ./
drwxr-xr-x 1 witlab witlab   1126  7월  8 11:19 ../
-rw------- 1 witlab witlab 492351  7월  5 17:24 SURFACE_ASOS_129_MI_2017-01_2017-01_2017.zip
...(생략)...
-rwxr-xr-x 1 witlab witlab     99  7월  8 14:46 unzip_all.sh*

 

 

그럼 이제 정말 끝. 실행해본다.

$ ./unzip_all.sh
/home/witlab/asos/SURFACE_ASOS_129_MI_2017-01_2017-01_2017.zip
Archive:  /home/witlab/asos/SURFACE_ASOS_129_MI_2017-01_2017-01_2017.zip
  inflating: SURFACE_ASOS_129_MI_2017-01_2017-01_2017.csv  
/home/witlab/asos/SURFACE_ASOS_129_MI_2017-02_2017-02_2017.zip
Archive:  /home/witlab/asos/SURFACE_ASOS_129_MI_2017-02_2017-02_2017.zip
  inflating: SURFACE_ASOS_129_MI_2017-02_2017-02_2017.csv  
/home/witlab/asos/SURFACE_ASOS_129_MI_2017-03_2017-03_2017.zip
Archive:  /home/witlab/asos/SURFACE_ASOS_129_MI_2017-03_2017-03_2017.zip
  inflating: SURFACE_ASOS_129_MI_2017-03_2017-03_2017.csv  
...(생략)...
$

마지막에 오류가 하나 나는데 그것은 쉘 스크립트 자체를 unzip 시도하기 때문에 발생한 것으로, 무시하면 된다.

확인해보면 모두 잘 풀렸다.

 

 

이로써 초간단 자동압축해제 프로그램을 만들어보았다. 끝!

 

 

반응형