파일처리_20 처리 시작 전에 실행 권한을 확인해서 정상 동작이 가능한지 확인 후 실행하기

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

명령어: test, [
키워드: 파일 속성, 상태 확인, 파일 테스트, 권한
사용처: 스크립트 초기 설정 등에서 특정 파일의 존재 확인이나 권한 확인을 하고 싶을 때


실행예제

$ ./test.sh
start.

스크립트

#!/bin/sh

start_command="./start.sh"

if [ -x "$start_command" ]; then  # ------------------ 1(if문 전체)
    $start_command
else
    echo "ERROR: -x $start_command failed." >&2
    exit 1
fi

   

해설

이 스크립트는 현재 디렉터리에 있는 start.sh를 실행하는 간단한 스크립트입니다. start.sh를 실행할 수 있는지를 스크립트 내부에서 미리 확인해서 판별합니다. 여기서 start.sh는 무언가를 처리하는 스크립트로 가정했는데 이 예제는 “start.sh”를 출력합니다.

이 예제에서는 스크립트 안에서 다른 명령어를 실행할 수 있는지를 test 명령어에 파일실행 권한을 확인하는 -x 연산자를 붙여 확인합니다. 파일 상태를 조사하는 연산자는 많은데 자주 사용하는 것만 다음 표에 모아뒀습니다. 예를 들어 스크립트 기동 초기에 -w로 로그 디렉터리에 쓸 수 있는지 조사하거나 -r로 설정 파일을 읽을 수 있는지 확인하는 용도로 자주 사용합니다.

  • test 명령어 주요 연산자
연산자 설명
-d 파일이 존재하고 디렉터리라면 참
-e 파일이 존재하면 참
-b 파일이 존재하고 블록 스페셜 파일이면 참
-c 파일이 존재하고 캐릭터 스페셜 파일이면 참
-f 파일이 존재하고 일반 파일(regular file)이면 참
-L 파일이 존재하고 심볼링 링크라면 참
-r 파일이 존재하고 읽기 가능하면 참
-w 파일이 존재하고 쓰기 가능하면 참
-x 파일이 존재하고 실행 가능하면 참
-s 파일이 존재하고 크기가 0보다 크면 참
-O 파일이 존재하고 실행 중인 셸의 실효 사용자 ID가 소유자면 참
-S 파일이 존재하고 소켓 파일이면 참

더 많은 연산자가 있으므로 man test로 확인해보기 바랍니다.

지금까지 test 명령어라고 서술했는데 실제로는 1에서 if문에 있는 [는 제어 구조를 나타내는 괄호가 아니라 test 명령어와 같은 명령어입니다. 예를 들어 다음처럼 명령어 이름을 해설하는 type 명령어로 조사해보면 [명령어가 셸 내장 명령어라는 걸 알 수 있습니다.

  • [ 가 명령어라는 걸 확인하기
    $ type [
    [ is a shell builtin
    

      하지만 [ 명령어가 test 명령어와 다른 것은 [명령어는 마지막 인수로 닫는 괄호 ]가 필요하다 라는 점입니다. 따라서 if문 조건식에서 사용하면 조건 전체가 괄호로 둘러 쌓여서 보기 좋으므로 자주 쓰입니다. 예제 1은 아래처럼 작성할 수 있습니다.

    if test -x "$start_command"; then
    

    test 명령어는 조건 판단을 해서 그 결과가 참이면 종료 스테이터스로 0을 둘려줍니다.
    if 문에서는 이 종료 스테이터스에 따라 참거짓 값을 판별합니다.

일반적으로 if문 조건식으로 [ ]를 많이 사용하지만, test 명령어는 물론이고 그 외에도 종료 스테이터스를 판단하는 명령어는 뭐든 쓸 수 있습니다. 예를 들어 다음은 if문 조건식에서는 grep 명령어를 그대로 사용합니다. 여기서는 sample.txt 파일에 문자열 “bin”이 포함되었는지 확인합니다.

#!/bin/sh

if grep -q "bin" sample.txt ; then
  echo "sample.txt has string [bin]"
fi

grep 명령어는 일치한 문자열이 있을 때는 종료 스테이터스 0, 일치하지 않으면 1을 돌려주므로 if 조건식으로 사용할 수 있습니다.

   

주의사항

  • ‘만약 실행 가능한 파일이면 실행한다’ 라는 단순한 조건을 간단하게 작성하면 다음과 같습니다.
    test -x start.sh && ./start.sh
    

&&로 명령어를 연결하면 앞 명령어가 성공하면(즉 종료 스테이터스가 0이면) 다음 명령어를 실행하도록 지정할 수 있습니다. 여기서 test -x 명령어가 성공하면 실행 가능하다는 의미이므로 이어서 다음 명령어를 실행하는 것입니다.  

  • 이 예제에서는 셸 변수 start_command로 지정한 파일이 디렉터리인지 확인하지 않았습니다. 따라서 드문 경우지만 [start.sh]라는 이름의 디렉터리가 있으면 에러가 발생합니다. 잘 처리하려면 1의 if문을 아래와 같이 -f로 일반 파일인지 확인한 다음 실행해야 합니다. 이때 -a는 test 명령어로 AND를 의미하는 연산자입니다.
    if [ -f "$start_command" -a -x "$start_command" ]; then