어떤 방법이 있나요?원천쉘 스크립트가 자체 경로를 찾습니까? 내 주요 관심사는 bash
내 동료 중 일부가 tcsh
.
소싱으로 인해 현재 셸에서 명령이 실행되므로 여기서는 운이 좋지 않을 수 있습니다. 따라서 $0
여전히 소스 스크립트가 아닌 현재 셸을 호출합니다. 가장 좋은 아이디어는 source $script $script
첫 번째 위치 매개변수에 필요한 정보를 포함시키는 것입니다. 누구든지 더 좋은 방법이 있습니까?
분명히 말하자면 나는구입스크립트를 실행하는 대신:
source foo.bash
답변1
에서는 파일 tcsh
이 원본이거나 파일이 실행된 경우 $_
스크립트 시작 부분에 해당 위치가 포함됩니다 .$0
#!/bin/tcsh
set sourced=($_)
if ("$sourced" != "") then
echo "sourced $sourced[2]"
endif
if ("$0" != "tcsh") then
echo "run $0"
endif
큰 타격을 받은 경우:
#!/bin/bash
[[ $0 != $BASH_SOURCE ]] && echo "Script is being sourced" || echo "Script is being run"
답변2
변수를 활용하시면 될 것 같아요 $BASH_SOURCE
. 실행 경로를 반환합니다.
예시 스크립트:
인쇄 스크립트 경로.sh:
#!/usr/bin/env bash
echo "$BASH_SOURCE"
실행 가능하게 만드세요:
chmod +x print_script_path.sh
이 스크립트의 다양한 위치에 대해 예제가 실행되고 출력됩니다.
pbm@tauri ~ $ /home/pbm/print_script_path.sh
/home/pbm/print_script_path.sh
pbm@tauri ~ $ ./print_script_path.sh
./print_script_path.sh
pbm@tauri ~ $ source /home/pbm/print_script_path.sh
/home/pbm/print_script_path.sh
pbm@tauri ~ $ source ./print_script_path.sh
./print_script_path.sh
그럼 다음으로 경로가 상대 경로인지 확인해야 합니다. 상대적인 것이 아니라면 모든 것이 괜찮을 것입니다. 그렇다면 경로를 확인 pwd
하고 및 /
와 연결하는 데 사용할 수 있습니다 $BASH_SOURCE
.
답변3
이 솔루션은 tcsh가 아닌 bash에서만 작동합니다. ${BASH_SOURCE[0]}
함수 내에서 경로를 찾으려고 하면 일반적으로 제공되는 답변이 작동하지 않습니다.
나는 이 줄이 파일이 소스 파일로 실행되는지 아니면 스크립트로 실행되는지에 관계없이 항상 작동한다는 것을 발견했습니다.
echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
readlink
재귀적으로 또는 비재귀적으로 심볼릭 링크를 따르 려면 위에서 얻은 경로를 사용하세요.
큰따옴표는 경로의 공백이 결과를 배열로 분할하는 것을 방지하며 에 대해서뿐만 아니라 echo
사용되는 모든 컨텍스트에도 필요합니다. 배열 항목 사이에 단일 공백이 삽입 되므로 echo
경로에 두 개 이상의 연속 공백이 없으면 차이가 숨겨집니다.
다음은 이를 다른 제안 솔루션과 비교하는 스크립트입니다. source test1/test2/test_script.sh
또는 이라고 부르세요 bash test1/test2/test_script.sh
.
#
# Location: test1/test2/test_script.sh
#
echo $0
echo $_
echo "${BASH_SOURCE}"
echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
cur_file="${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
cur_dir="$(dirname "${cur_file}")"
source "${cur_dir}/func_def.sh"
function test_within_func_inside {
echo "${BASH_SOURCE}"
echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
}
echo "Testing within function inside"
test_within_func_inside
echo "Testing within function outside"
test_within_func_outside
#
# Location: test1/test2/func_def.sh
#
function test_within_func_outside {
echo "${BASH_SOURCE}"
echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
}
한 줄의 코드가 작동하는 이유는 BASH_SOURCE
환경 변수 및 관련 변수의 사용으로 설명할 수 있습니다 FUNCNAME
.
BASH_SOURCE
FUNCNAME 배열 변수에 해당 쉘 함수 이름을 정의하는 소스 파일 이름이 멤버인 배열 변수입니다. 쉘 함수 ${FUNCNAME[$i]}는 ${BASH_SOURCE[$i]} 파일에 정의되어 있으며 ${BASH_SOURCE[$i+1]}에서 호출됩니다.
기능 이름
현재 실행 중인 호출 스택에 있는 모든 셸 함수의 이름을 포함하는 배열 변수입니다. 인덱스 0의 요소는 현재 실행 중인 쉘 함수의 이름입니다. 맨 아래 요소(인덱스가 가장 높은 요소)는 "main"입니다. 이 변수는 쉘 함수가 실행될 때만 존재합니다. FUNCNAME에 대한 할당이 잘못되었으며 오류 상태를 반환합니다. FUNCNAME이 설정되지 않으면 나중에 재설정되더라도 특수 속성이 손실됩니다.
이 변수는 BASH_LINENO 및 BASH_SOURCE와 함께 사용할 수 있습니다. FUNCNAME의 각 요소에는 BASH_LINENO 및 BASH_SOURCE에 호출 스택을 설명하는 해당 요소가 있습니다. 예를 들어 ${FUNCNAME[$i]}는 ${BASH_SOURCE[$i+1]} 파일의 줄 번호 ${BASH_LINENO[$i]}에서 호출됩니다. 내장 호출자는 이 정보를 사용하여 현재 호출 스택을 표시합니다.
[출처: Bash 매뉴얼]
답변4
철저함과 검색자를 위해 그것이 바로 목적입니다... 커뮤니티 위키이므로 다른 쉘에 상응하는 항목을 자유롭게 추가하십시오(분명히 $BASH_SOURCE는 다를 것입니다).
테스트.sh:
#! /bin/sh
called=$_
echo $called
echo $_
echo $0
echo $BASH_SOURCE
test2.sh:
#! /bin/sh
source ./test.sh
큰 타격:
$./test2.sh
./test2.sh
./test2.sh
./test2.sh
./test.sh
$ sh ./test2.sh
/bin/sh
/bin/sh
./test2.sh
./test.sh
스프린트
$./test2.sh
./test2.sh
./test2.sh
./test2.sh
$/bin/sh ./test2.sh
/bin/sh
/bin/sh
./test2.sh
$
지쉬
$ ./test2.sh
./test.sh
./test.sh
./test.sh
$ zsh test.sh
echo
test.sh
$