티스토리 뷰

이번 학기에 오픈소스에 기여하는 프로젝트 과목을 수강하고 있습니다.

매주 진행사상 보고서를 작성하는 만큼, 티스토리 블로그에도 오픈소스 기여 과정을 업로드하면 좋겠다 싶어서 작성해요.

 

팀원 한 명과 함께 진행하는 프로젝트이고, 아래는 작성한 제안서 내용 일부를 가져왔습니다.

해당 옵션의 아이디어는 팀원이 제시하였고, 아래 제안서의 모든 내용은 팀원과 회의하여 함께 도출한 내용입니다.

팀원이 적은 부분은 인용 처리를 하였고, 나머지 개요와 옵션 사용 예시는 제가 작성해서 전체 다 올렸습니다 :)

 

 

 


0. 프로젝트 주제

rm 명령어 옵션: 디렉터리 삭제 시 삭제에서 제외할 파일 설정

 

1. 개요

어떤 디렉터리에서 일부 파일은 남기고 나머지만 삭제하고자 할 때가 있다. 유닉스/ 리눅스 체제에 익숙한 사용자라면 파일/디렉터리 삭제 명령어 rm과 찾기 명령어 find를 조합하여 사용할 수 있다. 그러나 여러 파일을 삭제에서 제외할 땐 두 명령어의 조합을 사용하기 불편하다. 예시를 들자면 다음과 같다.

/find 디렉터리에 1) a.txt 2) b.c 3) c.h 4) d.py 파일이 있다고 하자. 이때 a.txt와 b.c 파일은 제외한 채 /find 디렉터리 내 모든 파일을 삭제하려고 하면 “find . type f -and ! -name a.c and ! -name b.c | xargs rm -rvf”를 입력해야 한다.

-name [파일] -and를 반복해서 적어야 할 뿐만 아니라, 상당히 많은 파일을 삭제에서 제외해야 할 때는 입력 및 명령어 수정이 불편해진다. 또한 여러 개의 삭제 제외 파일을 입력한 후 제대로 입력했는지에 관한 확인 절차가 없으므로 사용자가 스스로 확인해야 하는 번거로움이 존재한다. 추가로 며칠 동안 사용하지 않으면 금세 잊어버릴 만큼 명령어가 깔끔해 보이지 않으며, 자칫 a.c 파일과 b.c 파일을 찾아서 삭제하라는 명령어처럼 보일 만큼 명령어가 직관적이지도 않다.

이런 번거로운 명령어와 옵션 대신 간단한 방법이 있기도 하다. 매번 파일 삭제 여부를 묻는 옵션을 사용하여 직접 삭제할 파일과 남겨둘 파일을 고를 수 있기 때문이다.

<rm -ri parent>

-i 옵션은 위 사진처럼 디렉터리 진입 여부와 파일 삭제 여부를 계속 확인한다. 위 캡처 화면에서는 child1.c 파일을 남겨두기 위해 /parent/child1.c를 제거하겠냐는 2번째 질문에 n (no)를 입력하였다.

지금은 테스트용으로 디렉터리와 파일 수가 적기 때문에 삭제 여부에 일일이 대답하는 것이 어렵지 않았다. 그러나 만약 삭제할 디렉터리와 파일 수가 많아진다면, 파일 몇 개를 남기겠다고 들이는 시간과 노력이 수고스러워진다.

한 마디로, ‘어떤 디렉터리에서 일부 파일은 남기고 나머지만 삭제’하는 간편한 명령어 옵션이 없다. 이 기능은 커맨드 라인이 아닌, 기본 컴퓨터 OS가 제공하는 Graphical User Interface 환경에서는 누구나, 자주 사용하는 것인 만큼, 유닉스/리눅스 터미널 창에서도 이 기능을 손쉽게 사용할 수 있기를 바란다.

물론, find 명령어와 rm 명령어를 Shell Script 파일로 만드는 방법도 있지만, 이는 몇 가지 불편함을 유발한다. 첫째, 사용자는 Shell Script 파일을 GitHub에서 따로 다운받아야 한다. Shell Script 파일은 기본 GNU 라이브러리의 rm 명령어 옵션으로 등록하지 못하기 때문이다. 둘째, 사용자가 별도로 Shell Script 실행 환경변수를 설정하여야 한다. 환경변수로 등록하지 않으면 Shell Script 파일이 있는 디렉터리에서만 이 기능을 사용할 수 있다. 따라서 실제 rm 명령어와 옵션처럼 어느 위치에서든 Shell Script 파일의 기능을 이용하려면 Shell Script 파일 실행 환경변수 등록이 필수이다.

이에, 본 프로젝트는 GNU coreuntils의 rm.c 파일에 직접 ‘디렉터리 삭제 시 삭제에서 제외할 파일이 있음을 의미하는 옵션’을 추가할 예정이다. 많은 사용자가 더욱 간단하고 간편하게 이 기능을 누릴 수 있는 환경을 제공하고자한다.

 

GitHub - coreutils/coreutils: upstream mirror

upstream mirror. Contribute to coreutils/coreutils development by creating an account on GitHub.

github.com

 

2. 옵션 이름

옵션 타입 사용법
Short option rm -rb [디렉터리명]
Long option rm -r [디렉터리명] --except-files

 

3. 옵션 사용 예시

터미널 창에 위 옵션 이름대로 -b 혹은 --except-files 옵션을 입력하면 다음과 같이 디렉터리 삭제 시 제외 할 파일들을 물어보는 프롬프트 창이 뜬다.

<터미널 창에서의 입력 관련 프로토타입>

첨부된 캡처 화면은 세부 기능을 설명하기 위한 입력 예시로, 삭제에서 제외할 파일 입력 관련 프로토타입이다. 위 프로토타입에서 Current Working Directory (CWD)는 ‘home/ kmi0817/opensource’이며, Sub Directory의 경로는 ‘home/kmi0817/opensource/parent’ 이다.

사용자가 특정 문구를 입력하기 전까지 프롬프트는 삭제에서 제외할 파일이 있냐는 질문을 반복한다. 즉, 사용자는 더 이상 입력할 파일이 없으면 “!no”를 입력하여 질문 루프에서 빠져나오며, 이와 동시에 디렉터리 삭제가 진행된다. 프롬프트에서 파일 입력 시 기본적으로 상대경로로 입력한다. 이때 여느 터미널 기능처럼 tab을 누르면 디렉토리명과 파일명이 자동으로 완성된다.

 

          I.    Current Working Directory 상의 파일을 입력하는 경우

경로명을 입력할 필요가 없다. 파일명과 확장자만 입력하면, 현재 디렉터리와 같은 위치에 존재한다고 간주한다. 위 프로토타입 캡처 화면에서는 첫 번째와 두 번째 입력 줄이 이에 해당한다.

 

         II.    Sub Directory 상의 파일을 입력하는 경우

경로명을 입력하되 서브 디렉터리 이름부터 입력하면 된다. 위 캡처 화면에서는 3번째 입력부터 이 상황에 대한 입력이다. CWD의 sub directory인 parent 상의 child1.c 파일을 삭제에서 제외하기 위해 /parent/child.c를 입력한 것이다.

 

        III.   Sub Directory 이름을 잘못 입력하는 경우

Shell이 입력받은 이름의 디렉터리를 찾는 데 실패한다면, 해당 디렉터리를 찾을 수 없다는 문구(Cannot find [입력 디렉터리 이름] directory)와 함께 다시 한번 입력(Please, check it again)을 받는다. 다시 입력할 때 사용자는 처음에 입력했듯이 디렉터리 이름뿐만 아니라, 파일 이름도 적어야 한다.

 

       IV.   파일 이름을 잘못 입력하는 경우

Shell이 입력받은 이름의 파일을 찾는 데 실패한다면, 해당 파일을 찾을 수 없다는 문구(Cannot find [입력 파일 이름] file)와 함께 다시 한번 입력(Please, check it again)을 받는다. 입력 방식은 기존 입력 방법과 똑같다. 현재 디렉터리와 동일선상의 파일은 ‘파일명.확장자’, 서브 디렉터리 내 파일은 ‘/서브디렉터리/파일명.확장자’로 입력해야 한다.

 

 

4. 삭제에서 제외된 파일 처리

삭제가 진행되기 전, 삭제된 디렉터리와 동일선상에 'remain-삭제일시'명의 디렉터리가 생성된다. 삭제에서 제외할 파일을 입력하고나면, 본 디렉터리에서 remain 디렉터리로 파일을 mv 시킨다. 파일이 모두 옮겨진 다음에 본격적인 디렉터리 내 모든 파일 삭제가 진행된다.

이때 삭제에서 제외된 파일들은 기존 상하위 경로를 구분하지 않은 채 remain 디렉터리에 임시 저장되기 때문에 파일의 구조가 뒤섞여 구분하기 어려운 단점이 있다. 이 문제를 해결하기 위해 remain 디렉터리 내부에 「pathLog.txt」라는 로그 파일도 함께 생성한다. 해당 로그 파일에는 복사된 파일들의 기존 경로를 텍스트로 가시화되어 있어, 어떤 하위 디렉터리 안에 있던 파일인지 확인할 수 있도록 한다.

 

 


솔직히 실제 GNU utils에 옵션을 추가할 수 있을 거라곤 생각하지 않지만 ㅎㅎ

그래도 그걸 목표로 옵션을 개발할 계획입니다.

pull request가 reject 된다면 그냥 깃 허브에 하나의 오픈 소스로 공개하는 것에 의미를 두려고 합니다.

오픈 소스를 개발하는 것도 오픈 소스에 기여하는 것이니까요!

728x90