Linux - Bash 쉘스크립트 파일의 절대경로 얻기

JS · 29 Jun 2019

쉘 스크립트(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이고 $1abc를 의미합니다.

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

정리

위의 방법들은 제가 쉘스크립트를 만들 때, 스크립트 파일의 절대경로를 얻기 위해 사용한 방법입니다. 이 외에 다른 여러가지 방법이 있을 수 있습니다. 참고바랍니다.

댓글을 보거나 쓰려면 이 버튼을 눌러주세요.
codechachaCopyright ©2019 codechacha