파일처리_02 명령어 사용법을 표시할 때 현재 파일명 표시하기(basename)

 
  • 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어

명령어: 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’“를 검색하면 이 방법을 쓴 기동 스크립트가 많이 보입니다.