- 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어
명령어: ls, case
키워드: 숨김 파일, 닷 파일
사용처: 숨김 파일만 대상으로 처리하고 싶을 때
실행예제
$ ./dotfile.sh
dot file: .bashrc
dot fiel: .cshrc
dot directory: .svn/
스크립트
#!/bin/sh
# IFS에 줄바꿈 설정
IFS='
' #----------------------------------------- 1
# 현재 디렉터리 아래에 있는 파일을 $filename으로 순서대로 처리
for filename in $(ls -AF) #----------------- 2
do
case "$filename" in #------------------- 3
.*/)
echo "dot directory: $filename"
;;
.*)
echo "dot file: $filename"
;;
esac
done
해설
이 스크립트는 현재 디렉터리에 있는 닷 파일(디렉터리)을 각각 파일인지 디렉터리인지 표시하여 열거합니다.
유닉스에서는 파일명 처음이 .(닷)이면 닷 파일이라고 부르며 숨김 파일로 다룹니다. 닷 파일은 명령어 설정 등 특수 용도로 사용하는 일이 많고 특별하게 다루기도 하므로 이 예제처럼 닷 파일만 대상으로 하는 스크립트도 필요할 때가 있습니다. 자주 쓰는 닷 파일을 표로 정리해 보았습니다.
-
자주 쓰는 닷 파일(디렉터리)
이름 용도 .bash_profile bash 로그인 시 읽어들이는 환경 설정 파일 .mysql_history mysql 멸영어 실행 이력 파일 .vimrc vi(vim) 에디터 환경 설정 파일 .DS_Store 파인더가 사용하는 폴더 정보 파일(Mac용) .ssh(디렉터리) ssh 접속용 키 파일 등을 저장. 비밀키를 포함하고 있으므로 주의가 필요 .svn(디렉터리) 서브 버전 작업 복사 관리 디렉터리 .git(디렉터리) Git 리포지터리 관리 디렉터리
이 스크립트는 닷 파일 목록을 ls 명령어로 작성하는데 사전 준비로 1
에서 IFS 변수를 변경합니다. 1
은 문장 도중에 줄바꿈이 있어서 잘못되어 보이지만 정상입니다.
IFS란 Internal Field Separator 약어로 셸이 사용하는 구분자로 해석하는 문자를 설정하는 특수 변수입니다. 기본값으로 줄바꿈, 탭, 스페이스가 설정됩니다. 1
은 이 IFS에 줄바꿈만 대입합니다. 이후 스크립트에서는 셸 구분자로 줄바꿈만 사용하고 스페이스와 탭은 사용하지 않기 위한 처리입니다.
이 예제에서는 파일명을 다루므로 파일명에 스페이스가 포함될 때마다 문자열로 다루는 불편함이 없도록 IFS로 줄바꿈만 설정해서 스페이스를 제외합니다. 변수 대입이 1
처럼 두 줄로 나뉘는 것은 다른 언어에서는 자주 볼 수 없는 형태이지만 셸 스크립트 IFS 설정에서는 비교적 자주 사용되는 방법입니다.
그럼 닷 파일은 ls 명령어를 쓰면 간단히 목록을 얻을 수 있을 것 같지만 단순히 *(애스터리스크)를 써서 ls * 하면 닷 파일은 대상에서 제외됩니다. 이것은 셸 사양에서 닷 파일을 *에 포함하지 않기 때문입니다.
ls 명령어 와일드 카드 지정으로 닷 파일을 얻으려면 .* 처럼 “닷 + 와일드카드”를 명시적으로 지정하는 방법이 있습니다. 하지만 현재 디렉터리를 의미하는 .과 부모 디렉터리를 의미하는 ..도 대상이 됩니다.
따라서 2
에서 ls 명령어 -A 옵션으로 닷 파일을 포함한 현재 디렉터리의 모든 파일을 표시하고 case 문으로 분류하는 방법으로 닷 파일만 추출합니다. ls -A라면 현재 디렉터리와 부모 디렉터리를 표시하지 않으므로 첫 문자가 .인지 아닌지라는 단순한 판별로 닷 파일을 추출할 수 있습니다.
그리고 2
에서는 파일인지 디렉터리인지 구별하기 위해 ls 명령어 -F 옵션도 함께 사용합니다. -F 옵션을 쓰면 디렉터리 마지막에 /를 붙이므로 이것을 보고 디렉터리인지 판단할 수 있습니다.
실제로 파일과 디렉터리를 판단하는 것은 3
case 문입니다. 셸 스크립트에서 문자열 일치로 처리 분기하고 싶을 때는 이런 case 문을 사용하면 간단합니다. 파일명이 .으로 시작해서 /로 끝나면 (.*/)
디렉터리로 보고 “dot directory”를 표시하고, 그 위에 .으로 시작하면 (.*)
파일로 보고 “dot file”을 표시합니다.
주의사항
-
1
에서 변경한 IFS 변수는 그대로 두면 다른 처리에서 부작용이 발생할 수 있으므로 변경하기 전 값을 저장해두고 사용이 끝나면 원래 값으로 돌려두는 것이 좋습니다.IFS_BACKUP=$IFS IFS=' ' # (어떤 처리를 실행) IFS=$IFS_BACKUP
-
IFS에 줄바꿈을 지정하는 다른 방법입니다. 이쪽이 줄바꿈이라는 걸 이해하기 쉽지만 POSIX 표준이 아니므로 우분투 sh 등 일부 환경에서는 제대로 동작하지 않습니다.
IFS=$'\n'