- 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어
명령어: basename
키워드: 파일명, 명령행 인수, 스크립트명
사용처: 도움말 표시나 로그 출력 시 파일명을 출력하고 싶을 때
실행 예제
$ /home/user1/myapp/basename.sh
Usage: basename.sh <string>
$ /home/user1/myapp/basename.sh HELLO
Start: basename.sh ...
Input Argument: HELLO
Stop: basename.sh ...
스크립트
#!/bin/sh
prog=$(basename "$0") # ------------------- 1
# 인수가 하나가 아니면 도움말을 표시하고 종료
if [$# -ne 1 ]; then # -------------------- 2
echo "Usage: $prog <string>" 1>&2 # ----- 3
exit 1
fi
# 명령행 인수 $1 표시
echo "Start: $prog ..." # ----------------- 4
echo " Input Argument: $1" # -------------- 4
echo "Stop: $prog ..." # ------------------ 4
해설
이 스크립트는 다음 조건으로 명령행 인수를 표시합니다.
- 명령행 인수가 하나뿐이면 그 값을 표시한다.
- 명령행 인수가 없거나 두개 이상이면 사용법을 표시한다.
1
에서 자신의 파일명을 스크립트 안에서 취득해 그 값을 셸 변수 prog에 저장한 뒤 도움말 표시 등에 사용하는 것이 이 예제의 포인트입니다. 셸 스크립트는 이식성이 뛰어난 프로그램이므로 복사해서 이런 저런 곳에서 사용하는 일이 많습니다. 그럴 때 파일명을 직접 스크립트 내부에 작성해서 사용하면(이것을 하드코드라고 부릅니다) 실제 파일명과 달라서 혼란이 발생하곤 합니다.
따라서 스크립트는 1
에서 파일명을 참조해서 얻습니다. 여기서 사용하는 basename 명령어는 다음처럼 파일 경로를 나타내는 문자열에서 경로 부분을 제거하고 파일명만 추출합니다.
-
basename 명령어는 파일명만 취득
$ basename "home/user1/myapp/script.sh" script.sh $ basename "./script.sh" script.sh
1
에서는 변수 $0
에 대한 basename 명령어 출력을 명령어 치환 $() 로 셸 변수 prog에 대입합니다. 변수 $0
은 셸 스크립트에서 사용하는 특수한 변수로 셸 스크립트가 실행될 때의 명령어 이름이 됩니다. 셸 스크립트는 전체 경로로 실행될 수도 있고 상대 경로로 실행될 수도 있지만 앞서 본 것처럼 제대로 파일명을 취급할 수 있습니다.
한편, 이런 특수한 변수 $0
과 비슷한 명령행 인수를 나타내는 위치 파라미터가 있는데 셸에서는 $0을 위치 파라미터가 아니라 특수 파라미터로 다룹니다. 자세한 내용은 man sh로 매뉴얼에 있는 특수 파라미터(Special Parameter) 항목을 참조하기 바랍니다.
이어서 2
에서 명령행 인수를 확인합니다. 변수 $#에는 인수 수가 들어 있으므로 이 값이 1이 아니라면 에러 처리합니다. 이때 에러 메시지로 3
처럼 Usage(사용법)를 표시합니다. 이것은 에러 메시지이므로 1>&2로 표준에러 출력을 사용합니다.
이렇게 Usage를 표시할 때는 주로 $0
에서 취득한 스크립트 파일명을 서서 도움말을 표시합니다. 다음처럼 코드에 직접 파일명을 작성하는 것은 좋지 않습니다.
echo "Usage: basename.sh <string>" 1>&2
지금 당장은 괜찮아도 나중에 누군가가 파일명을 바꾸면 스크립트 안에 있는 이름도 바꿔야 합니다.
반면에 파일명을 $0
으로 취득하면 파일명이 변해도 스크립트 자체를 수정하지 않아도 됩니다. 나중을 생각해서라도 파일명을 하드 코딩하지 맙시다.
4
는 지정한 인수값을 출력합니다. $1
은 명령행 인수 첫 번째 값을 나타냅니다. 여기에서는 스크립트 동작 로그로 변수 prog값을 함께 출력해서 나중에 로그 파일을 보았을 때 어떤 스크립트가 출력한 로그인지 알기 쉽도록 합니다.
주의사항
-
자신의 파일명을 취득할 때 basename 명령어 대신에 다음처럼 쓸 수있습니다.
prog=${0##*/}
이것은 셸 파라미터 확장을 이용한 예입니다. ${parameter##word}는 변수 parameter 값에서 word에 마지막으로 일치하는 부분을 삭제한 값을 얻을 수 있습니다. 즉 이 예에서는 word로 */가 지정되어 있으므로 ‘변수 $0에서 [임의의문자열/]를 삭제한 값’ 즉, 파일명만 취득할 수 있습니다.
-
Usage 에러 메시지를 표시할 때
$0
으로 스크립트명을 표시하는 방법은 시스템 도구에서 자주 사용됩니다. 리눅스에서 /etc/init.d 아래에 있는 셸 스크립트 대상으로 “grep ‘$0’“를 검색하면 이 방법을 쓴 기동 스크립트가 많이 보입니다.