[Linux 셸 스크립트] 파일처리 - 023 절대 경로, 상대 경로 관계없이 같은 동작하기
본문 바로가기
IT 이야기/Linux 셸 스크립트

[Linux 셸 스크립트] 파일처리 - 023 절대 경로, 상대 경로 관계없이 같은 동작하기

by 찬찬이 아빠 2021. 3. 11.
반응형
  1. 사용 명령어

(1) cd

(2) dirname

 

  2. 키워드 & 사용처

(1) 키워드

절대 경로, 상대 경로, 전체 경로, cron

 

(2) 사용처

cron 동에서 스크립트를 전체 경로로 실행할 때 상대 경로로 실행한 것과 같은 동작을 하고 싶을 때 사용합니다.

 

 

  3. 실행 예제
$ cd /home/park
$ /home/park/myapp/dirname.sh
START
END

 

 

  4. 스크립트

#!/bin/sh

 

cd "$(dirname "$0")"             

 

./start.sh

./end.sh

 

 

  5. 해설

이 스크립트는 두 외부 파일 start.sh와 end.sh를 순서대로 실행합니다. 여기서 start.sh와 end.sh 두 파일은 /home/park/myapp 디렉터리에 설치되어 있고 각 파일의 내용은 "START", "END"입니다.

 

그런데 셸 스크립트 내부에서 다른 셸 스크립트를 실행할 때는 경로에 주의해야 합니다. 그렇지 않으면 아래 예제처럼 만들지도 모릅니다.


#!/bin/sh

 

./start.sh

./end.sh


 

스크립트를 작성할 때는 셸 스크립트 파일이 저장된 디렉터리를 현재 디렉터리로 작업하는 일이 많으므로 위의 스크립트는 정상적으로 동작합니다. 하지만 스크립트를 완성해서 cron에 등록해서 정기적으로 실행한다면 이 스크립트는 다음처럼 에러를 발생할지도 모릅니다.

/home/park/myapp/dirname.sh: line 3: ./start.sh: No such file or directory
/home/park/myapp/dirname.sh: line 4: ./end.sh: No such file or directory

 

이처럼 직접 실행할 땐 정상이었지만 cron에 등록해서 배치 처리할 때 제대로 동작하지 않는 상황은 심심치 않게 벌어집니다. 이것은 cron 실행 시 현재 디렉터리가 cron 실행 사용자의 홈 디렉터리가 되기 때문입니다. 즉, cron에서 dirname.sh가 실행되면 현재 디렉터리는 /home/park가 되어 여기서 ./start.sh를 지정하면 /home/park/start.sh 파일을 찾게 됩니다. 스크립트 내부에서 다른 셸 스크립트를 실행하는 프로그램은 아래처럼 외부 스크립트 파일을 전체 경로로 지정하는 방법도 사용합니다.


#!/bin/sh

 

/home/park/myapp/start.sh

/home/park/myapp/end.sh


 

하지만 이때 스크립트가 있는 디렉터리(myapp) 이름이 바뀌면 문제가 생기며 이식성도 낮습니다. 따라서 상대 경로를 사용하고 싶기 마련입니다. 이런 문제를 해결하려면 셸 스크립트가 일단 '자신이 지정된 디렉터리에 cd 명령어로 이동해서 처리를 시작하도록' 만들면 됩니다.

 

에서 사용하는 dirname 명령어는 전체 경로가 오면 디렉터리 부분을 추출할 수 있습니다. $0은 실행된 셸의 명령어 자체를 뜻하는 변수로 이 예제에서는 "/home/park/myapp/dirname.sh"가 들어 있습니다.

$ dirname "/home/park/myapp/dirname.sh"
/home/park/myapp

 

$()은 명령어 치환 표기로 명령어 출력을 그대로 스크립트에서 이용할 수 있습니다. 즉 ①은 'dirname "$0" 출력 결과 디렉터리에 cd 명령어로 이동한다' 라는 의미입니다. 이 예제에서라면 /home/park/myapp 디렉터리에 cd 명령어로 이동합니다.

 

이렇게 하면 셸 스크립트는 자신이 존재하는 디렉터리로 cd 명령어를 써서 이동할 수있습니다. 따라서 상대 경로이거나 절대 경로이거나 상관없이 외부 셸 스크립트를 상대 결로로 실행할 수 있습니다.

 

 

<주의사항>

  • 디렉터리명에 스페이스(공백문자)가 포함되더라도 정상적으로 동작하도록①에서 $0 및 명령어 치환 전체를 큰따옴표 기호로 감쌉니다..
  • dirname 명령어를 쓰지 않아도 다음처럼 작성할 수 있습니다.
cd "${0%/*}"

 

이것은 셸 파라미터 확장을 이용한 예입니다. ${parameter%word}라고 하면 변수 parameter 값에서 word에 후방 일치하는 부분을 삭제한 값을 취득할 수 있습니다. 즉 word로 /*가 지정되었으므로 '변수 $0 뒤에서부터 "/임의의 문자열"을 삭제한 값' 즉, 디렉터리 부분만 얻을 수 있습니다. dirname 명령어라는 외부 명령어를 쓰지 않아도 셸 기능만으로 구현 가능하므로 이쪽을 선호하는 사람도 있습니다.

 

 

 

참고서적 : 유닉스 리눅스 셸 스크립트 예제 사전

반응형

댓글