쉘 스크립트(Shell script, bash shell)를 실행할 때 스크립트 파일의 경로를 알아야 할 때가 있습니다.
리눅스 쉘의 실행 위치와 관련없이 쉘스크립트 파일의 절대경로를 얻는 방법에 대해서 알아보겠습니다.
쉘에서 sh
명령어로 직접 스크립트를 실행하는 경우가 있으며, source
명령어로 환경변수만 읽어오는 경우가 있습니다.
두가지 케이스에 대해서 다른 방법을 적용하여 절대경로를 얻었습니다.
이 글의 코드는 우분투18.04에서 확인하였습니다.
스크립트를 실행하는 쉘의 경로 얻기
쉘에서 pwd -P
명령어를 사용하면 현재 쉘의 절대경로를 알 수 있습니다.
이것을 스크립트에 적용해보면 아래처럼 사용할 수 있습니다. `명령어`처럼 명령어 양쪽에 `를 써주면 명령어의 결과가 변수에 대입된다는 의미입니다.
#!/bin/sh
SHELL_PATH=`pwd -P`
echo $SHELL_PATH
따라서, 위 스크립트를 실행해보면 아래처럼 스크립트를 실행하는 쉘의 경로를 출력해줍니다.
~$ pwd
/home/js
~$ ls test/myscript.sh
test/myscript.sh
~$ sh ./test/myscript.sh
/home/js
/test$ sh ./myscript.sh
/home/js/test
결국 이 방법으로 쉘스크립트 파일의 절대경로를 얻을 수 없습니다. 스크립트를 실행하는 쉘의 위치에 따라서 결과가 달라집니다.
스크립트를 실행할 때, 스크립트 파일의 경로 얻기
위의 코드를 응용하면 스크립트 파일의 절대경로를 얻을 수 있습니다. 스크립트를 실행할 때 명령어를 인자로 받는데요, 그 인자의 경로를 해석해서 파일의 위치를 구하는 것입니다. 아래처럼 구현할 수 있습니다.
#!/bin/sh
echo 'PARAM:' $0
RELATIVE_DIR=`dirname "$0"`
echo 'Dir:' $RELATIVE_DIR
cd $RELATIVE_DIR
SHELL_PATH=`pwd -P`
echo $SHELL_PATH
$0
은 명령어의 첫번째 인자를 의미합니다. 예를들어 sh ./myscript.sh abc
라는 명령어가 있다면
$0
은 ./myscript.sh
이고 $1
은 abc
를 의미합니다.
dirname
은 문자열에서 디렉토리만 추출해주는 명령어입니다.
dirname ./myscript.sh
은 ./
를 리턴합니다. 파일의 상대경로를 얻고, 쉘이 그 위치로 이동한 다음 pwd
명령어로 절대경로를 얻으면 스크립트 파일의 절대경로를 얻을 수 있습니다.
결과는 아래와 같습니다.
~/test$ sh myscript.sh
PARAM: myscript.sh
Dir: .
Script Dir: /home/js/test
~$ sh test/myscript.sh
PARAM: test/myscript.sh
Dir: test
Script Dir: /home/js/test
정리하면, 위의 코드를 한줄로 이렇게 표현할 수 있습니다.
DIR="$( cd "$( dirname "$0" )" && pwd -P )"
echo $DIR
readlink으로 파일 경로 얻기
readlink
를 이용하여 위와 동일한 결과를 얻을 수 있습니다.
readlink
는 아래와 같이 canonical file name을 얻는데 사용되는 command입니다.
NAME
readlink - print resolved symbolic links or canonical file names
DESCRIPTION
Note realpath(1) is the preferred command to use for canonicalization functionality.
Print value of a symbolic link or canonical file name
-f, --canonicalize
canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist
다음은 readlink
를 사용하여 위와 동일한 결과를 출력하는 코드입니다.
#!/bin/sh
echo 'PARAM:' $0
RELATIVE_DIR=`dirname "$0"`
echo 'Dir:' $RELATIVE_DIR
CANONICAL_DIR=`readlink -f $RELATIVE_DIR`
echo 'CANONICAL DIR:' $CANONICAL_DIR
결과
~/test$ sh myscript.sh
PARAM: myscript.sh
Dir: .
CANONICAL DIR: /home/js/test
~$ sh test/myscript.sh
PARAM: test/myscript.sh
Dir: test
CANONICAL DIR: /home/js/test
스크립트를 Source할 때, 스크립트 파일의 경로 얻기
위에서 작성한 스크립트를 source
명령어로 실행하면 동작하지 않습니다. $0
이 인자를 리턴하지 않기 때문입니다.
source
를 사용할 때는 $0
대신 $BASH_SOURCE
를 사용하면 됩니다.
#!/bin/sh
echo 'PARAM:' $BASH_SOURCE
RELATIVE_DIR=`dirname "$BASH_SOURCE"`
echo 'Dir:' $RELATIVE_DIR
cd $RELATIVE_DIR
SHELL_PATH=`pwd -P`
echo 'Script Dir:' $SHELL_PATH
위의 스크립트를 source
로 실행하면 아래처럼 출력이 됩니다.
~$ source test/myscript.sh
PARAM: test/myscript.sh
Dir: test
Script Dir: /home/js/test
정리하면, 위의 코드를 한줄로 이렇게 표현할 수 있습니다.
DIR="$( cd "$( dirname "$BASH_SOURCE" )" && pwd -P )"
echo $DIR
readlink으로 파일 경로 얻기
다음은 readlink
를 이용하여 위와 동일한 결과를 출력하는 코드입니다.
#!/bin/sh
echo 'PARAM:' $BASH_SOURCE
RELATIVE_DIR=`dirname "$BASH_SOURCE"`
echo 'Dir:' $RELATIVE_DIR
CANONICAL_DIR=`readlink -f $RELATIVE_DIR`
echo 'CANONICAL DIR:' $CANONICAL_DIR
결과
~/test$ source myscript.sh
PARAM: myscript.sh
Dir: .
CANONICAL DIR: /home/js/test
~$ source test/myscript.sh
PARAM: test/myscript.sh
Dir: test
CANONICAL DIR: /home/js/test
정리
위의 방법들은 제가 쉘스크립트를 만들 때, 스크립트 파일의 절대경로를 얻기 위해 사용한 방법입니다. 이 외에 다른 여러가지 방법이 있을 수 있습니다. 참고바랍니다.
Recommended Posts:
- Ubuntu 20.04 - SSH 설치와 접속 방법
- Ubuntu에서 imwheel로 마우스 휠 스크롤 속도 변경
- Ubuntu 20.04 - OpenJDK 11 설치, 삭제
- Ubuntu 20.04 - VLC Player 설치
- Ubuntu에서 사용할 수 있는 Text Editor 소개
- apt remove, purge, autoremove 명령어 차이점
- Linux의 apt-get 명령어
- Ubuntu 20.04 - 토렌트 설치
- Ubuntu에서 사용할 수 있는 그림판(mspaint)과 비슷한 툴 소개
- Linux - Hardware 정보를 보여주는 명령어
- Ubuntu에 OpenJdk 9 설치하는 방법
- AutoKey 설치 및 macro 만들기
- Ubuntu18.04의 네트워크 이더넷 이름 변경하는 방법(enp??를 eth0으로 변경)