Bash 스크립트에서 스크립트 파일 이름을 어떻게 알 수 있습니까?


605

스크립트 자체 내의 Bash 스크립트 파일 이름을 어떻게 확인할 수 있습니까?

내 스크립트가 파일 runme.sh에있는 것처럼 하드 코딩없이 "Your running runme.sh"메시지를 표시하려면 어떻게해야합니까?


3
비슷한 [bash 스크립트가 어떤 디렉토리에 저장되어 있는지 알 수 있습니까?] (to stackoverflow.com/questions/59895/… )
Rodrigue

답변:


630
me=`basename "$0"`

일반적으로 원하는 것이 아닌 symlink 1을 읽으 려면 (일반적으로 사용자를 혼동하지 않으려는 경우) 다음을 시도하십시오.

me="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"

IMO는 혼란스러운 결과를 낳습니다. "foo.sh를 실행했지만 bar.sh를 실행 중입니다!? 버그 여야합니다!" 또한 다른 이름의 심볼릭 링크를 사용하는 목적 중 하나는 이름에 따라 다른 기능을 제공하는 것입니다 (일부 플랫폼에서는 gzip 및 gunzip을 생각하십시오).


1 에,이다 해결 심볼릭 링크 등 사용자가 실행 때 foo.sh실제로 심볼릭 링크에 bar.sh, 당신은 확인 된 이름을 사용하고자하는 bar.sh것이 아니라 foo.sh.


40
$ 0은 실제 스크립트 파일의 실제 경로가 아니라 스크립트가 호출 된 이름을 제공합니다.
Chris Conway

4
symlink를 통해 호출되지 않는 한 작동합니다. 그러나 그럼에도 불구하고 일반적으로 IME입니다.
Tanktalus

78
호출되는 대신 소스로 작성된 스크립트에는 작동하지 않습니다.
Charles Duffy


8
-1, 1. readlink는 하나의 symlink 심도 만 이동합니다. 2. $0첫 번째 예에서는 단어 분할이 적용됩니다. 3. $0basename, readlink 및 echo에 전달되어 명령 행 스위치로 처리 될 수있는 위치 . me=$(basename -- "$0")가독성을 희생하면서 대신 또는 훨씬 더 효율적으로 제안합니다 me=${0##*/}. me=$(basename -- "$(readlink -f -- "$0")")gnu 유틸리티를 가정하면 심볼릭 링크의 경우 그렇지 않으면 여기에 쓰지 않을 매우 긴 스크립트가됩니다.
Score_Under

246
# ------------- SCRIPT ------------- #


#!/bin/bash

echo
echo "# arguments called with ---->  ${@}     "
echo "# \$1 ---------------------->  $1       "
echo "# \$2 ---------------------->  $2       "
echo "# path to me --------------->  ${0}     "
echo "# parent path -------------->  ${0%/*}  "
echo "# my name ------------------>  ${0##*/} "
echo
exit

# ------------- 호출 ------------- ## ------------- 호출 ------------- #

# 다음 줄에서 첫 번째 인수는 double 내에서 호출됩니다. # 다음 줄에서 첫 번째 인수는 double 내에서 호출됩니다. 
두 단어를 포함하므로 # 및 작은 따옴표두 단어를 포함하므로 # 및 작은 따옴표

$ /misc/shell_scripts/check_root/show_parms.sh " 'hello there'" " 'william'"/ misc / shell_scripts / check_root / show_parms . sh " '안녕하세요'" " 'william'" 

# ------------- 결과 ------------- ## ------------- 결과 ------------- #

---> 'hello there' 'william'와 함께 호출 된 인수---> 'hello there' 'william'와 함께 호출 된 인수
# $ 1 ----------------------> '안녕하세요'# $ 1 ----------------------> '안녕하세요'
# $ 2 ----------------------> 'william'# $ 2 ----------------------> 'william'
# 나에게 경로 --------------> /misc/shell_scripts/check_root/show_parms.sh# 나에게 경로 --------------> /misc/shell_scripts/check_root/show_parms.sh
# 부모 경로 -------------> / misc / shell_scripts / check_root# 부모 경로 -------------> / misc / shell_scripts / check_root
# 내 이름 -----------------> show_parms.sh# 내 이름 -----------------> show_parms.sh

# ------------- 끝 ------------- ## ------------- 끝 ------------- #


1
show_params선택적 확장자가없는 이름 즉, 어떻게해야 합니까?
Acumenus

다른 폴더에서 스크립트가 호출 된 경우 작동하지 않습니다. 경로는에 포함되어 있습니다 ${0##*/}. GitBash를 사용하여 테스트했습니다.
AlikElzin-kilaka

1
위의 내용은 .bash_login 스크립트에서 작동하지 않지만 $ BASH_SOURCE의 Dimitre Radoulov 솔루션은 훌륭하게 작동합니다.
John

@ John 확실하게 .bash_profile 을 의미 합니까? 또는 .bashrc ? 호출 / 소싱 방법에 미묘한 차이점이 있음을 알아야합니다. 나는 피곤하다. 그러나 내가 올바르게 생각하고 있다면 그것은 아마도 문제 일 것이다. 중요한 것은 ssh 대 로컬 시스템과 같이 원격으로 시스템에 로그인하는 경우입니다.
Pryftan

193

bash는> = 3 개 다음 작품 :

$ ./s
0 is: ./s
BASH_SOURCE is: ./s
$ . ./s
0 is: bash
BASH_SOURCE is: ./s

$ cat s
#!/bin/bash

printf '$0 is: %s\n$BASH_SOURCE is: %s\n' "$0" "$BASH_SOURCE"

24
큰! 즉 두 ./scrip.sh 및 소스 ./script.sh 작동 답이다
zhaorufei

4
이것이 내가 원하는 것이며, " dirname $BASE_SOURCE"를 사용 하여 스크립트가있는 디렉토리를 쉽게 얻을 수 있습니다.
Larry Cai

2
자체 삭제 스크립트를 작성할 때 그 차이를 거의 알지 못했습니다. 운 좋게도 'rm'은 'rm -i'로 별칭이 지정되었습니다.
kervin

어쨌든. bash 대신 ./s라는 이름을 얻으려면? 나는 $ 1이 항상 ./s로 설정되는 것은 아니라는 것을 알았습니다.
David Mokon Bond

1
이 글은 다음의 BASH_SOURCE , 그렇지?
Dimitre Radoulov

69

$BASH_SOURCE 스크립트를 소싱 할 때 정답을 제공합니다.

그러나 여기에는 경로가 포함되므로 스크립트 파일 이름 만 얻으려면 다음을 사용하십시오.

$(basename $BASH_SOURCE) 

2
이 답변은 솔루션이 자체 문서화 코드를 사용하기 때문에 IMHO가 가장 좋습니다. $ BASH_SOURCE 예 : $ {0 ## * /}하지 반면 모든 문서를 읽지 않고 완전히 이해할 수있다
안드레아스 M. Oberheim

우리가 같이 실행하면 때문 대답은 더 많은 가치를 내가 믿음입니다 . <filename> [arguments], $0발신자 쉘의 이름을 줄 것입니다. 적어도 OSX에서는 확실합니다.
Mihir

68

스크립트 이름에 공백이 있으면 MacOS 를 사용 "$0"하거나 "$(basename "$0")"MacOS 에서보다 강력한 방법을 사용 하십시오 "$(basename \"$0\")". 이렇게하면 이름이 엉망이되거나 해석되지 않습니다. 일반적으로 쉘에서 변수 이름을 항상 큰 따옴표로 묶는 것이 좋습니다.


2
정답 + 간결한 +1 symlink 기능이 필요한 경우 Travis B. Hartwell의 답변을 참조하십시오.
Trevor Boyd Smith

26

경로없이 원한다면 사용하십시오. ${0##*/}


선택적 파일 확장자없이 원하는 경우 어떻게합니까?
Acumenus

확장을 제거하려면 "$ {VARIABLE % .ext}"를 시도하면됩니다. 여기서 VARIABLE은 $ {0 ## * /}에서 얻은 값이고 ".ext"는 제거 할 확장입니다.
BrianV

19

Chris Conway에 대답하려면 Linux에서 적어도 다음을 수행하십시오.

echo $(basename $(readlink -nf $0))

readlink는 기호 링크의 값을 인쇄합니다. 심볼릭 링크가 아닌 경우 파일 이름을 인쇄합니다. -n은 개행을 인쇄하지 않도록 지시합니다. -f는 링크를 완전히 따르도록 지시합니다 (심볼릭 링크가 다른 링크에 대한 링크 인 경우 해당 링크도 해결합니다).


2
-n은 무해하지만 $ (...) 구조가 트리밍하기 때문에 필요하지는 않습니다.
zhaorufei

16

파일이 소스인지 스크립트로 실행되는지에 관계 없이이 줄이 항상 작동하는 것으로 나타났습니다.

echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"

readlink위의 경로에서 심볼릭 링크를 사용하려면 재귀 적으로 또는 비재 귀적으로 사용하십시오.

one-liner가 작동하는 이유는 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_LINENO [$ i]}의 $ {BASH_SOURCE [$ i + 1]} 파일에서 호출되었습니다. 발신자 기본 제공은이 정보를 사용하여 현재 호출 스택을 표시합니다.

[출처 : 배쉬 매뉴얼]


2
대화 형 세션 에서 파일을 소스 a ( a의 내용이 있다고 가정)로 작동하면 경로 echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"가 제공됩니다 a. 당신은 스크립트를 작성하지만 만약 bsource a그것의 실행 ./b, 그것은 돌아갑니다 b'의 경로를.
PSkocik

12

이 답변은 상황에 따라 맞지만 'source'키워드를 사용하여 다른 스크립트에서 스크립트를 실행하면 동일한 쉘에서 실행되므로 여전히 문제가 있습니다. 이 경우 호출 스크립트의 $ 0를받습니다. 그리고이 경우 스크립트 자체의 이름을 얻는 것이 가능하지 않다고 생각합니다.

이것은 엣지 케이스이며 너무 심각하게 생각해서는 안됩니다. 다른 스크립트에서 직접 ( 'source'없이) 스크립트를 실행하면 $ 0을 사용하는 것이 좋습니다.


2
당신은 아주 좋은 지적이 있습니다. 엣지 케이스 IMO가 아닙니다. 하지만 해결책이있다 : 참조 Dimitre Radoulov의 대답 위
서지 Wautier

10

일부 의견은 확장명이없는 파일 이름에 대해 물었으므로 다음과 같은 방법을 사용하십시오.

FileName=${0##*/}
FileNameWithoutExtension=${FileName%.*}

즐겨!


9

Re : 위의 Tanktalus (허용됨) 대답은 약간 더 깨끗한 방법입니다.

me=$(readlink --canonicalize --no-newline $0)

스크립트가 다른 bash 스크립트에서 제공 되었다면 다음을 사용할 수 있습니다.

me=$(readlink --canonicalize --no-newline $BASH_SOURCE)

귀하의 목표가 사용자에게 피드백을 제공하는 것이 목적이라면 심볼릭 링크를 역 참조하는 것이 혼란 스러울 것입니다.하지만 정식 이름을 스크립트 또는 다른 파일로 가져와야하는 경우가 있습니다.


1
sourced 스크립트 이름에 감사드립니다 .
Fredrick Gauss

8

$ 0을 사용하여 스크립트 이름 (전체 경로)을 결정할 수 있습니다. 스크립트 이름 만 얻으려면 해당 변수를

basename $0

8

쉘 스크립트를 호출하면

/home/mike/runme.sh

$ 0은 이름입니다

 /home/mike/runme.sh

기본 이름 $ 0은 기본 파일 이름을 가져옵니다.

 runme.sh

이 기본 이름을 다음과 같은 변수에 넣어야합니다.

filename=$(basename $0)

추가 텍스트를 추가하십시오

echo "You are running $filename"

그래서 당신의 스크립트는

/home/mike/runme.sh
#!/bin/bash 
filename=$(basename $0)
echo "You are running $filename"

7
this="$(dirname "$(realpath "$BASH_SOURCE")")"

이렇게하면 심볼릭 링크가 해결되고 (실제로 처리) 공백을 처리하고 (큰 따옴표로 처리), 소스 (. ./myscript)를 제공하거나 다른 스크립트 ($ BASH_SOURCE가 처리)에서도 현재 스크립트 이름을 찾습니다. 결국 재사용하거나 다른 곳에서 쉽게 복사하기 위해 환경 변수에 저장하는 것이 좋습니다 (this =) ...


3
FYI realpath는 내장 BASH 명령이 아닙니다. 특정 배포판에서만 사용할 수있는 독립 실행 형 실행 파일
StvnW

4

에서 bash를 사용하여 스크립트 파일 이름을 얻을 수 있습니다 $0. 일반적으로 $1, $2등 액세스 CLI 인수에 있습니다. 마찬가지로 $0스크립트 (스크립트 파일 이름)를 트리거하는 이름에 액세스하는 것입니다.

#!/bin/bash
echo "You are running $0"
...
...

당신은 같은 경로로 스크립트를 호출하면 /path/to/script.sh다음 $0또한 경로와 파일 이름을 제공 할 것입니다. 이 경우 $(basename $0)스크립트 파일 이름 만 가져와야합니다.


3
echo "$(basename "`test -L ${BASH_SOURCE[0]} \
                   && readlink ${BASH_SOURCE[0]} \
                   || echo ${BASH_SOURCE[0]}`")"

2

$0질문에 대답하지 않습니다. 데모 :

$ 고양이 script.sh
#! / bin / sh
에코`기본 이름 $ 0`
$ ./script.sh 
script.sh
ln script.sh linktoscript
$ ./linktoscript 
링크

어떻게 ./linktoscript인쇄 할 수 script.sh있습니까?

[편집] 위의 주석에서 @ephemient에 따르면 심볼릭 링크가 고안된 것처럼 보일지 모르지만 $0파일 시스템 리소스를 나타내지 않도록 바이올린을 피울 수 있습니다. OP는 그가 원하는 것에 대해 약간 모호합니다.


위의 답변에 이것에 대한 답변을 추가했지만, 이것이 실제로 원하는 것 (또는 내가 현재 추측 할 수없는
소멸

2
script.sh 대신 linktoscript를 인쇄하는 것이 버그가 아닌 기능이라고 생각합니다. 몇몇 유닉스 명령어들은 그들의 행동을 바꾸기 위해 그들의 이름을 사용합니다. 예는 vi / ex / view입니다.
mouviciel 2016 년

@Tanktalus : 파일의 실제 위치를 기반으로 동작을 변경하려는 경우가 있습니다. 이전 프로젝트에서 "Active branch"스크립트를 사용했습니다.이 스크립트는 지점의 여러 도구 경로에 연결됩니다. 작업; 그런 다음 해당 도구는 올바른 파일에 대해 실행하기 위해 체크 아웃 한 디렉토리를 찾을 수 있습니다.
Andrew Aylett

2

Bill Hernandez 덕분에 정보. 내가 선호하는 환경 설정을 추가했습니다.

#!/bin/bash
function Usage(){
    echo " Usage: show_parameters [ arg1 ][ arg2 ]"
}
[[ ${#2} -eq 0 ]] && Usage || {
    echo
    echo "# arguments called with ---->  ${@}     "
    echo "# \$1 ----------------------->  $1       "
    echo "# \$2 ----------------------->  $2       "
    echo "# path to me --------------->  ${0}     " | sed "s/$USER/\$USER/g"
    echo "# parent path -------------->  ${0%/*}  " | sed "s/$USER/\$USER/g"
    echo "# my name ------------------>  ${0##*/} "
    echo
}

건배


1

짧고 명확하며 간단합니다. my_script.sh

#!/bin/bash

running_file_name=$(basename "$0")

echo "You are running '$running_file_name' file."

넣어 :

./my_script.sh
You are running 'my_script.sh' file.


0

저는 여기에서 영감을 해낸 것입니다 Dimitre Radoulov 의 대답 (나는 방법에 의해 upvoted한다) .

script="$BASH_SOURCE"
[ -z "$BASH_SOURCE" ] && script="$0"

echo "Called $script with $# argument(s)"

스크립트 호출 방식에 관계없이

. path/to/script.sh

또는

./path/to/script.sh

-1

echo "당신은 $ 0을 실행하고 있습니다"


bash 스크립트가 아니며 전체 경로입니다.
e-info128

-6

이 같은 것?

export LC_ALL=en_US.UTF-8
#!/bin/bash
#!/bin/sh

#----------------------------------------------------------------------
start_trash(){
ver="htrash.sh v0.0.4"
$TRASH_DIR  # url to trash $MY_USER
$TRASH_SIZE # Show Trash Folder Size

echo "Would you like to empty Trash  [y/n]?"
read ans
if [ $ans = y -o $ans = Y -o $ans = yes -o $ans = Yes -o $ans = YES ]
then
echo "'yes'"
cd $TRASH_DIR && $EMPTY_TRASH
fi
if [ $ans = n -o $ans = N -o $ans = no -o $ans = No -o $ans = NO ]
then
echo "'no'"
fi
 return $TRUE
} 
#-----------------------------------------------------------------------

start_help(){
echo "HELP COMMANDS-----------------------------"
echo "htest www                 open a homepage "
echo "htest trash               empty trash     "
 return $TRUE
} #end Help
#-----------------------------------------------#

homepage=""

return $TRUE
} #end cpdebtemp

# -Case start
# if no command line arg given
# set val to Unknown
if [ -z $1 ]
then
  val="*** Unknown  ***"
elif [ -n $1 ]
then
# otherwise make first arg as val
  val=$1
fi
# use case statement to make decision for rental
case $val in
   "trash") start_trash ;;
   "help") start_help ;;
   "www") firefox $homepage ;;
   *) echo "Sorry, I can not get a $val   for you!";;
esac
# Case stop

5
-1, 질문에 답하지 않고 (스크립트 이름을 찾는 방법을 보여주지 않음) 매우 버그가 많은 스크립트에서 혼란스러운 예입니다.
Score_Under
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.