source, . (점): 셸 스크립트 파일 실행
목차
배시(Bash)에서 source
와 .
은 동일한 기능을 하는 명령어로, 셸 스크립트 파일을 실행하는 데 사용합니다.
소개 link
source
와 .
은 파일을 실행하는 명령어입니다. 좀 이상하게 생기긴 했지만 .
도 엄연한 하나의 명령어입니다.
예시:
다음과 같이 셸 스크립트 파일을 만듭니다. 여기서는 asdf.sh
라는 이름으로 만들겠습니다:
echo Hello
다음 명령어로 셸 스크립트를 실행합니다:
source asdf.sh
. asdf.sh
source
와 .
모두 asdf.sh
를 실행합니다. Hello
가 두 번 출력되는 것을 확인할 수 있습니다.
source
vs bash
link
source
(또는 .
)와 유사한 명령어로 bash
가 있습니다. 인자로 파일 이름을 주면 셸 스크립트 파일을 실행합니다. 다음과 같이 사용 방법도 같습니다:
source asdf.sh
bash asdf.h
이 둘의 차이가 무엇일까요?
역할 link
두 명령어 모두 셸 스크립트 파일을 실행하는 데 사용할 수 있습니다.
사용 셸 link
반면 이 둘은 새로운 셸을 만드는 데 있어 차이를 보입니다.
source
: 현재 셸에서 스크립트 파일을 실행합니다.
bash
: 새로운 셸을 만들어 스크립트 파일을 실행합니다. 셸에서 선언된 변수나 현재 작업 디렉터리(cd
를 통해 이동할 수 있는 그것)의 위치는 해당 셸에서만 유효하며, 셸이 종료되면 모두 사라집니다.
이로 인해 몇 가지 차이가 발생합니다. 대표적으로 환경 변수 유효성과 cd
로 인한 경로 유지에 관한 차이가 있습니다.
환경 변수 유효성 link
source
: 스크립트 안에서 선언한 환경 변수를 스크립트 바깥에서 접근할 수 있습니다.
bash
: 스크립트 안에서 선언한 환경 변수는 스크립트 바깥에서 접근할 수 없으며 스크립트가 끝나면 그대로 소멸합니다. 스크립트 바깥에서의 접근을 원한다면 export
명령어를 통해야 합니다.
예시:
먼저 asdf.sh
파일을 만듭니다:
TEST_VALUE=123
echo "In file: $TEST_VALUE"
이제 이 파일을 다음처럼 실행합니다 (반드시 bash
가 source
보다 앞서 등장해야 합니다):
bash asdf.sh
echo "bash asdf.sh: $TEST_VALUE"
source asdf.sh
echo "source asdf.sh: $TEST_VALUE"
출력 결과:
In file: 123
bash asdf.sh:
In file: 123
source asdf.sh: 123
bash
는 123
이 출력되지 않은 반면, source
는 123
이 출력되었습니다. 여기서 우리는 bash
로 인해 실행한 asdf.sh
의 경우, 실행이 끝나면 더 이상 변수가 유효하지 않음을 확인할 수 있습니다.
cd
로 인한 경로 유지 link
source
: 스크립트 안에서 cd
를 실행한 결과가 그대로 유지됩니다.
bash
: 스크립트 안에서의 cd
는 스크립트 안에서 유지되지만, 스크립트 바깥에서는 유지되지 않습니다.
예시:
먼저 asdf.sh
파일을 만듭니다. 이 예시에서는 /home/ubuntu
에 만들겠습니다. (pwd
는 현재 작업 디렉터리를 출력하는 명령어입니다):
echo "In file 1: $(pwd)"
cd ..
echo "In file 2: $(pwd)"
이제 이 파일을 다음처럼 실행합니다. (반드시 bash
가 source
보다 앞서 등장해야 합니다):
pwd
bash asdf.sh
pwd
source asdf.sh
pwd
출력 결과:
/home/ubuntu
In file 1: /home/ubuntu
In file 2: /home
/home/ubuntu
In file 1: /home/ubuntu
In file 2: /home
/home
bash asdf.sh
는 스크립트 파일 내부의 현재 작업 디렉터리를 바꾸었지만, 스크립트 파일 바깥은 연향을 받지 않았습니다. 반면, source
는 스크립트 파일 바깥에서도 현재 작업 디렉터리에 영향을 주었습니다.
요약 link
역할 | 사용 셸 | 환경 변수 유효성 | cd 로 인한 경로 유지 |
|
---|---|---|---|---|
source |
스크립트 파일 실행 | 현재 셸 | ✔️ 파일 바깥에서 접근 가능 | ✔️ 파일 바깥에서 유지됨 |
bash |
스크립트 파일 실행 | 새로운 셸 | ❌ 파일 바깥에서 접근 불가 | ❌ 파일 바깥에서 유지 안 됨 |
source
vs .
link
두 명령어의 기원: C 셸과 본 셸 link
C 셸(csh)과 본 셸(sh)은 각각 1978년, 1979년 만들어진 오래된 셸입니다. C 셸은 source
, 본 셸은 .
명령어만 지원합니다.
배시의 두 명령어는 본 셸과 C 셸로부터 유래한 것으로 보입니다. 이를 통해 배시는 오래된 셸들과의 호환성을 확보할 수 있습니다.
왜 source
가 더 권장되는가: fish 셸 link
fish 셸의 개발자는 .
명령어에 대해 다른 명령어와 혼동되고, 발견하기 어려우며, .
이라는 명령어를 모르는 사람으로 하여금 .
을 지칭하거나 소리내어 읽을 수 없다는 문제가 있음을 지적했습니다. 이로 인해 아예 .
을 폐기하고 source
만을 지원하기로 했습니다1.
두 명령어의 기능이 다른 셸: Z 셸 link
Z 셸(zsh)은 조금 독특합니다.
source
명령어의 경우 배시처럼 현재 작업 디렉터리에서만 스크립트 파일을 찾는 것에서 끝나지 않습니다. 스크립트 파일을 찾을 수 없다면 PATH
환경 변수에 존재하는 경로들로부터도 스크립트 파일을 찾습니다2.
특이하게도 .
는 source
와 동일한 동작을 하지 않고 약간 차이가 있습니다. source
와 반대 순서로 먼저 PATH
환경 변수를 찾고 그 다음 현재 작업 디렉터리에서 스크립트 파일을 찾습니다3.
혼동 주의: ./asdf.sh
와 . asdf.sh
link
./asdf.sh
와 . asdf.sh
를 혼동하지 마세요. ./asdf.sh
는 bash asdf.sh
와 동일합니다.
참고 link
- Dot (command) - Wikipedia
- What is the difference between “source” and “.”? - Ask Ubuntu: 관련 스택오버플로 질문
- Bash: using dot or “source” calling another script - what is difference? - Stack Overflow: 관련 스택오버플로 질문
- running script with “. ” and with “source ” - Unix & Linux: 관련 스택오버플로 질문
-
https://github.com/fish-shell/fish-shell/issues/310#issuecomment-22645318
I think fish simply shouldn’t ever have
.
, considering it’s confusing (with auto-cd), non-discoverable, and cryptic (if I would see it in code, without knowing about it, I simply couldn’t say anything about it). But considering changing.
tosource
would break lots of scripts, I decided to go with soft deprecation - the.
command still works, … -
17 Shell Builtin Commands - zsh
source file [ arg … ] Same as ‘.’, except that the current directory is always searched and is always searched first, before directories in $path.
-
17 Shell Builtin Commands - zsh
. file [ arg … ] If file does not contain a slash, or if PATH_DIRS is set, the shell looks in the components of $path to find the directory containing file. Files in the current directory are not read unless ‘.’ appears somewhere in $path.