쉘 스크립트(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
정리
위의 방법들은 제가 쉘스크립트를 만들 때, 스크립트 파일의 절대경로를 얻기 위해 사용한 방법입니다. 이 외에 다른 여러가지 방법이 있을 수 있습니다. 참고바랍니다.
Related Posts
- Ubuntu/Linux - 특정 이름이 들어간 파일 모두 찾고 삭제하기
- Ubuntu/Linux - 특정 이름이 포함된 프로세스 모두 종료
- Ubuntu/Linux - 사용자 계정 이름 확인 (id, whoami)
- Ubuntu/Linux - E: unable to locate package 에러 해결
- Ubuntu 22.04/20.04 - Yarn 설치 방법
- Linux/Ubuntu - grep 명령어로 문자열 검색
- Linux/Ubuntu - 터미널에서 seq로 명령어 N회 반복
- Linux/Ubuntu - wc 명령어로 Line(줄) 개수 세기
- bash: pip: command not found 문제 해결 (Linux/Ubuntu)
- Ubuntu 22.04 - Swap 메모리 늘리기
- Linux - 파일이 수정된 날짜/시간 확인 방법
- Linux - 파일, 디렉토리 삭제 명령어(rm -rf, rmdir)
- 우분투 22.04 - deb 파일 설치하기
- Ubuntu 20.04 - OpenJDK 11 설치, 삭제
- Linux - ps 명령어로 실행 중인 프로세스(PID) 확인
- Ubuntu 20.04 - SSH 설치와 접속 방법
- Ubuntu에서 PPA 저장소 추가, 제거 방법
- Ubuntu 22.04 - Brave 브라우저 설치
- Ubuntu 22.04 - 프로스트와이어(FrostWire) 설치
- Ubuntu 22.04 - Remmina 설치 방법
- Ubuntu 22.04 - Rust 설치하기
- Ubuntu 22.04 - 텔레그램 설치하기
- Ubuntu - Deluge 토렌트 클라이언트 설치
- Ubuntu JDK 17 (OpenJDK) 설치, 삭제
- Ubuntu 20.04 스팀(Steam) 설치 방법
- Ubuntu에서 draw.io 설치하는 방법
- 우분투에 VMware 설치하기
- [Ubuntu] VMware에서 Windows 11 설치
- Vi/Vim에서 1줄 또는 여러줄 삭제 방법
- Vi/Vim에서 라인 번호 표시하 기
- 우분투에서 rar 압축, 압축 풀기
- Ubuntu에서 구글 드라이브 사용하기 (로컬 폴더에 마운트)
- [Ubuntu] apt-cache search, 설치 가능한 패키지 검색
- Ubuntu - DNS 캐시 삭제 방법
- Ubuntu에서 사용할 수 있는 Text Editor 소개