다음과 같은 폴더 구조를 가진 작은 프로그램이 있습니다.
- main.sh
- lib/
- clean.sh
- get.sh
- index.sh
- test.sh
각 파일에는 i 가 포함되어 있습니다 main.sh
.
main.sh
:
source lib/*
get_products
clean_products
make_index
test_index
위의 예에서 처음 두 함수는 작동하지만 마지막 두 함수는 작동하지 않습니다.
하지만 다음으로 바꾸면 source lib/*
:
source lib/get.sh
source lib/clean.sh
source lib/index.sh
source lib/test.sh
모든 것이 예상대로 작동합니다.
source lib/*
이것이 예상대로 작동하지 않는 이유를 아는 사람이 있습니까 ?
답변1
Bash의 source
내장 명령은 단일 파일 이름만 사용합니다.
source filename [arguments]
첫 번째 인수 이외의 모든 인수는 위치 인수가 됩니다 filename
.
간단한 예:
$ cat myfile
echo "param1: $1"
$ source myfile foo
param1: foo
모든 출력help source
source: source filename [arguments]
Execute commands from a file in the current shell.
Read and execute commands from FILENAME in the current shell. The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.
Exit Status:
Returns the status of the last command executed in FILENAME; fails if
FILENAME cannot be read.
.
(이는 특히 POSIX이므로 이식성이 더 좋은 내장된 "포인트 소스"에도 적용됩니다 .)
당신이 보고 있는 겉보기에 모순된 동작에 대해서는 완료 후 main.sh를 실행해 볼 수 있습니다 set -x
. 어떤 명령문이 언제 실행되었는지 확인하면 단서를 얻을 수 있습니다.
답변2
배쉬 문서source
단일에 적용됨 을 나타냅니다.파일 이름:
. (일정 기간)
.파일 이름[논쟁]
다음에서 명령을 읽고 실행합니다.파일 이름현재 쉘 컨텍스트의 매개변수입니다. 만약에파일 이름...
그리고 소스코드...원천...이를 지원합니다:
result = source_file (filename, (list && list->next));
source_file
정의는 어디에 있습니까?evalfile.c
부르다 _evalfile
:
rval = _evalfile (filename, flags);
그리고 _evalfile
파일만 엽니다.
fd = open (filename, O_RDONLY);
답변3
보완적인레이어 b에 대한 유용한 답변, 확장하려는 유형의 파일이 존재하는지 확실하지 않은 경우 욕심 많은 전역 확장을 사용하지 않는 것이 좋습니다.
다음을 수행하면 (확장자 없음) 파일이 실행될 수 있는 유해한 명령(예: 실행 권한이 있다고 가정)이 .sh
포함된 임시 파일인 것처럼 보일 수 있습니다.rm -rf *
source lib/*
따라서 *.sh
파일을 개별적으로 반복할 수 있더라도 항상 전역 확장을 위해 적절한 바인딩 세트를 사용하십시오.
for globFile in lib/*.sh; do
[ -f "$globFile" ] || continue
source "$globFile"
done
이는 현재 폴더에 일치하는 전역 패턴이 없는 경우 [ -f "$globFile" ] || continue
루프에서 반환되며 , 이는 셸의 확장 셸 옵션과 동일합니다.nullglob
bash