1. 사용 명령어 |
(1) head
(2) mv
2. 키워드 & 사용처 |
(1) 키워드
셔뱅, shebang, 확장자, 첫줄
(2) 사용처
확장자가 없는 스크립트 파일에 자동으로 확장자를 부여하고 싶을 때 사용합니다.
3. 실행 예제 |
$ ./shebang.sh script
'script' -> 'script.sh'
$ ./shebang.sh sample1
'sample1' -> 'sample1.pl'
4. 스크립트 |
#!/bin/sh
# 대상 스크립트 파일이 있는지 확인
if [ ! -f "$1" ]; then ①
echo "지정한 파일을 찾지 못했습니다: $1" >&2
exit 1
fi
# 파일 첫 줄 읽음
headline=$(head -n 1 "$1") ②
# 파일 첫 줄에 따라 확장자를 판정해서 부여함
case "$headline" in ③
*/bin/sh|*bash*)
mv -v "$1" "${1}.sh"
;;
*perl*)
mv -v "$1" "${1}.pl"
;;
*ruby*)
mv -v "$1" "${1}.rb"
;;
*)
echo "Unknown Type: $1"
esac
5. 해설 |
이 스크립트는 스크립트 파일 첫 줄을 읽어서 사용된 언어에 대응하는 확장자를 파일명에 부가합니다.
관례적으로 스크립트 파일은 해당 언어에 대응하는 확장자를 파일명에 사용합니다. 일반적으로 사용하는 확장자는 다음 표와 같습니다.
확장자 | 언어 |
sh | sh, bash |
pl | Perl |
rb | Ruby |
py | Python |
php | PHP |
하지만 확장자는 어디까지나 관례이므로 셸 스크립트를 포함해서 스크립트 파일은 확장자가 없더라도 동작합니다. 따라서 셸 스크립트를 작성할 때 .sh를 붙이지 않는 사람도 있습니다.
여러분이 관리하는 시스템에도 확장자가 없는 스크립트가 존재할지도 모릅니다. 파일명 만으로도 어떤 언어로 만들어졌는지 알 수 있도록 그런 스크립트의 확장자를 일괄적으로 추가하고 싶을 때가 있을 겁니다. 그럴 때 이 예제를 사용하면 좋습니다.
셸 스크립트의 첫 줄은 반드시 #!로 시작합니다.
#!/bin/sh
이를 셔뱅(Shebang)이라고 합합니다.유닉스에서는 파일을 실행할 때 그 파일이 기계어로 작성된 파일이라면 그대로 실행합니다. 그렇지 않으면 파일 첫 줄을 읽어서 #! 뒤에있는 명령어를 실행합니다. 위 예에서는 /bin/sh가 실행되므로 셸 스크립트로 동작하게 됩니다.
이런 셔뱅의 동작을 이해하기 위해 다음과 같은 실험을 해봅시다.
C언어 등으로 작성된 실행 파일(기계어 파일)과 셸 스크립트 파일은 실행하기 위한 최소 퍼미션이 다릅니다. C 언어 등으로 만든 실행 파일은 읽기 퍼미션이 없어도 실행 권한이 있으면 실행됩니다.
C언어로 작성한 실행 파일은 실행 비트만으로도 실행이 가능합니다.
$ chmod 100 a.out
$ ls -l a.out
---x------ 1 park park 6425 Apr 7 16:40 a.out*
$ ./a.out
Hello, World.
셸 스크립트 파일은 일반 사용자로 실행할 때는 실행 권한만으로는 실행되지 않고 반드시 읽기 권한도 있어야 합니다.
$ chmod 100 ptest.sh
$ ls -l ptest.sh
---x------ 1 park park 29 Apr 7 17:30 ptest.sh*
$ p./ptest.sh
/bin/sh: ./ptest.sh: Permission denied
sh ./ptest.sh라고 해석되므로 ptest.sh에 읽기 권한이 있어야만 합니다(단, root 사용자는 그대로 실행할 수 있습니다).
예제에서는 이 셔뱅을 봐서 파일 종류를 판별해 확장자를 부여합니다.
우선 ①에서는 대상 스크립트 파일을 확인합니다. test 명령어 -f 연산자로 파일이 존재하는지 확인해서 부정 연산자 !를 사용해 파일이 존재하지 않을 때 에러를 표시하고 종료합니다.
이어서 ②에서는 head 명령어로 파일 첫 줄을 추출해서 셸 변수 headline에 저장합니다. head 명령어는 파일 앞부분 부터 읽는 명령어로 -n 옵션을 사용하면 지정한 줄 수만 추출할 수 있습니다. 여기서 -n 1을 지정해서 첫 줄만 추출해서 셔뱅만 취득합니다.
③에서 case문을 사용해 파일 종류를 판단합니다. mv 명령어를 이용해서 */bin.sh | *bash*와 일치하면(sh 또는 bash 스크립트) 확장자를 .sh로, *perl*와 일치하면 .pl로, *ruby*와 일치하면 .rb로 파일명을 변경합니다. 명령어 뒤에 *를 붙이는 것은 옵션 지정을 위해 뒤에 스페이스나 옵션이 이어져도 일치하도록 하기 위함입니다.
그리고 확장자 변경 mv 명령어에 -v 옵션을 써서 변경 전후 파일명을 표시합니다.
③ case문 마지막에서 *를 이용해 지금까지 일치하지 않은 그 외의 파일은 "Unknown Type:" 이라고 표시하고 파일명을 변경하지 않습니다.
<주의사항>
이 스크립트는 펄, 루비, sh, bash에만 대응합니다. 만약 루비가 /usr/bin/perl/ruby 같은 경로에 설치되었다면 오동작하게 됩니다.
이미 확장자가 설정되어 있는지 확인하지 않으므로 상황에 따라서는 ptest.pl.pl처럼 확장자가 이중으로 지정될 수도 있습니다.
파일 종류를 알 수없을 때는file 명령어가 편리합니다. file 명령어는 다음처럼 파일을 인수로 지정해서 그 파일이 무엇인지 판단해서 표시합니다.
$ file /usr/bin/startx
/usr/bin/startx: POSIX shell script text executable
$ file network.dat
network.dat: tcpdump capture file (little-endian) - version 2.4(Ethernet, capture length 65535)
위 예에서 첫 번째 startx 파일은 셸 스크립트, 두 번째 network.dat 파일은 tcpdump한 패킷 캡쳐 파일입니다. 그리고 file 명령어는 "'매직 파일'이라는 일종의 '파일 사전'이 있어서 이것을 보고 파일 종류를 판단합니다.
head 명령어와 반대로 파일 끝에서부터 읽는 tail 명령어도 있습니다.
참고서적 : 유닉스 리눅스 셸 스크립트 예제 사전
'IT 이야기 > Linux 셸 스크립트' 카테고리의 다른 글
[Linux 셸 스크립트] 텍스트 처리 - 072 CSV 파일에서 지정한 특정 레코드의 컬럼값 얻기 (0) | 2021.04.08 |
---|---|
[Linux 셸 스크립트] 텍스트 처리 - 071 입력 파일 해시값을 줄마다 추가해서 출력하기 (0) | 2021.04.08 |
[Linux 셸 스크립트] 텍스트 처리 - 069 텍스트 파일에서 구분자를 지정해서 컬럼 추출하기 (0) | 2021.04.07 |
[Linux 셸 스크립트] 텍스트 처리 - 068 ID가 적힌 목록 파일에서 ID를 추출할 때 ID 끝 문자로 정렬하기 (0) | 2021.04.07 |
[Linux 셸 스크립트] 네트워크 - 067 로컬 셸 스크립트 파일을 원격 호스트에서 그대로 실행하기 (0) | 2021.04.07 |
댓글