การกำหนดพา ธ ไปยังเชลล์สคริปต์ที่มา


80

มีวิธีการที่เป็นแหล่งเชลล์สคริปต์เพื่อหาเส้นทางของตัวเองหรือไม่ ฉันกังวลเกี่ยวกับทุบตีเป็นหลักแม้ว่าฉันจะมีเพื่อนร่วมงานบางคนที่ใช้ tcsh

ฉันเดาว่าฉันอาจไม่มีโชคที่นี่เนื่องจากการหาสาเหตุทำให้คำสั่งถูกเรียกใช้ในเชลล์ปัจจุบันดังนั้นจึง$0ยังคงเป็นการเรียกใช้เชลล์ปัจจุบันไม่ใช่สคริปต์ที่มา ความคิดที่ดีที่สุดของฉันคือการทำsource $script $scriptเพื่อให้พารามิเตอร์ตำแหน่งแรกมีข้อมูลที่จำเป็น ใครมีวิธีที่ดีกว่า

เพื่อความชัดเจนฉันกำลังจัดหาสคริปต์ไม่ใช่เรียกใช้:

source foo.bash

คำถามที่เกี่ยวข้องที่มีผู้โหวตมากกว่า 4200 คน: stackoverflow.com/q/59895/52074
Trevor Boyd Smith

คำตอบ:


65

ในtcsh, $_ที่จุดเริ่มต้นของสคริปต์จะมีสถานที่ตั้งหากไฟล์ที่ได้รับมาและ$0มีมันถ้ามันกำลังวิ่ง

#!/bin/tcsh
set sourced=($_)
if ("$sourced" != "") then
    echo "sourced $sourced[2]"
endif
if ("$0" != "tcsh") then
    echo "run $0"
endif

ใน Bash:

#!/bin/bash
[[ $0 != $BASH_SOURCE ]] && echo "Script is being sourced" || echo "Script is being run"

ฉันมีโอกาสที่จะใช้สิ่งนี้ใน tcsh และสังเกตเห็นว่ามันไม่สามารถทำงานได้หากไม่มี shebang ดูเหมือนแปลกเล็กน้อยสำหรับพฤติกรรมที่จะเปลี่ยนหากคุณเพียงแค่จัดหามันไม่ได้ดำเนินการ ...
Cascabel

รุ่น tcsh นั้นดูเหมือนว่าจะไม่ทำงานหากสคริปต์นั้นมีแหล่งที่มาแบบไม่โต้ตอบ (เช่นจาก cshrc) ฉันไม่สามารถหาวิธีรับข้อมูลได้ในกรณีนี้ ความคิดใด ๆ
Cascabel

การจัดหามันใช้งานได้สำหรับฉันโดยไม่ต้องมี shebang > tcsh --version\n tcsh 6.14.00 (Astron) 2005-03-25 (i486-intel-linux) options wide,nls,dl,al,kan,rh,nd,color,filec. เท่าที่การจัดหามันไม่โต้ตอบไฟล์ต้นฉบับจะรวมอยู่ในไฟล์แม่ราวกับว่ามันเป็นส่วนหนึ่งของมัน (แยกไม่ออก) ตามที่คุณพูดถึงในคำถามเดิมของคุณ ฉันคิดว่าการแก้ปัญหาตำแหน่งพารามิเตอร์ของคุณน่าจะเป็นวิธีที่ดีที่สุด อย่างไรก็ตามคำถามทั่วไปคือ "ทำไมคุณต้องการทำเช่นนั้น" และคำตอบปกติในการตอบกลับคือ "ไม่ทำอย่างนั้น - ทำสิ่งนี้แทน" โดยที่ "นี่" มักจะเก็บไว้ ...
Dennis Williamson

2
@clacke: ฉันพบว่าในทุกเวอร์ชั่นของ Bash ที่ฉันทดสอบจาก 2.05b ถึง 4.2.37 รวมถึง 4.1.9 นั้น.และใช้sourceงานได้เหมือนกันในเรื่องนี้ โปรดทราบว่า$_จะต้องเข้าถึงได้ในคำสั่งแรกในไฟล์มิฉะนั้นจะมีอาร์กิวเมนต์ล่าสุดของคำสั่งก่อนหน้า ฉันชอบที่จะรวม Shebang ไว้สำหรับอ้างอิงของฉันเองดังนั้นฉันจึงรู้ว่าควรใช้เชลล์ตัวใดและสำหรับตัวแก้ไขดังนั้นจึงใช้การเน้นไวยากรณ์
Dennis Williamson

1
ฮ่าฮ่า เห็นได้ชัดว่าฉันถูกทดสอบโดยการทำครั้งแรกแล้วทำsource .ฉันขอโทษที่ไร้ความสามารถ พวกเขาเหมือนกันแน่นอน อย่างไรก็ตาม$BASH_SOURCEงาน
clacke

30

ฉันคิดว่าคุณสามารถใช้$BASH_SOURCEตัวแปร จะส่งคืนพา ธ ที่ถูกดำเนินการ:

pbm@tauri ~ $ /home/pbm/a.sh 
/home/pbm/a.sh
pbm@tauri ~ $ ./a.sh
./a.sh
pbm@tauri ~ $ source /home/pbm/a.sh 
/home/pbm/a.sh
pbm@tauri ~ $ source ./a.sh
./a.sh

ดังนั้นในขั้นตอนต่อไปเราควรตรวจสอบว่าเส้นทางนั้นสัมพันธ์หรือไม่ ถ้ามันไม่สัมพันธ์กันทุกอย่างก็โอเค ถ้าเป็นเราสามารถตรวจสอบเส้นทางที่มีpwd, concatenate ด้วยและ/$BASH_SOURCE


2
และทราบว่าsourceการค้นหาในถ้าชื่อที่กำหนดไม่ได้มี$PATH /ลำดับการค้นหาขึ้นอยู่กับตัวเลือกของเชลล์อ้างถึงคู่มือสำหรับรายละเอียด
Gilles

1
ดังนั้นสิ่งที่ชอบmydir="$(cd "$(dirname "$BASH_SOURCE")"; pwd)"จะทำงานอย่างไร
Kevin Cantu

ขอบคุณคำตอบที่รวดเร็วและเป็นประโยชน์ เดนนิสชนะเครื่องหมายถูกสีเขียวสำหรับให้คำตอบ tcsh ด้วย @Gilles: ใช่ฉันพบว่าในเอกสาร โชคดีสำหรับกรณีการใช้งานของฉันฉันเกือบจะไม่ต้องกังวลกับมัน
Cascabel

17

วิธีนี้ใช้ได้เฉพาะกับ bash ไม่ใช่ tcsh โปรดทราบว่าคำตอบที่ให้มาโดยทั่วไป${BASH_SOURCE[0]}จะไม่ทำงานหากคุณพยายามหาเส้นทางจากภายในฟังก์ชั่น

ฉันพบว่าบรรทัดนี้ใช้งานได้เสมอไม่ว่าไฟล์นั้นจะมาจากแหล่งไหนหรือทำงานเป็นสคริปต์ก็ตาม

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

หากคุณต้องการติดตามการใช้ symlink readlinkบนเส้นทางที่คุณได้รับด้านบนเรียกซ้ำหรือไม่เรียกซ้ำ

ต่อไปนี้เป็นสคริปต์เพื่อทดลองใช้และเปรียบเทียบกับโซลูชันที่เสนออื่น ๆ เรียกว่ามันเป็นหรือsource test1/test2/test_script.shbash 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]}

FUNCNAME

ตัวแปรอาร์เรย์ที่มีชื่อของฟังก์ชั่นเชลล์ทั้งหมดในปัจจุบันในการเรียกการเรียกใช้งาน องค์ประกอบที่มีดัชนี 0 เป็นชื่อของฟังก์ชั่นเปลือกที่กำลังดำเนินการใด ๆ ในปัจจุบัน องค์ประกอบด้านล่างสุด (องค์ประกอบที่มีดัชนีสูงสุด) คือ "หลัก" ตัวแปรนี้มีอยู่เฉพาะเมื่อมีการเรียกใช้ฟังก์ชันเชลล์ การกำหนดให้กับ FUNCNAME จะไม่มีผลใด ๆ และส่งคืนสถานะข้อผิดพลาด หาก FUNCNAME ไม่ได้ตั้งค่ามันจะสูญเสียคุณสมบัติพิเศษแม้ว่าจะถูกรีเซ็ตในภายหลัง

ตัวแปรนี้สามารถใช้กับ BASH_LINENO และ BASH_SOURCE แต่ละองค์ประกอบของ FUNCNAME มีองค์ประกอบที่เกี่ยวข้องใน BASH_LINENO และ BASH_SOURCE เพื่ออธิบายสแตกการโทร ตัวอย่างเช่น $ {FUNCNAME [$ i]} ถูกเรียกจากไฟล์ $ {BASH_SOURCE [$ i + 1]} ที่หมายเลขบรรทัด $ {BASH_LINENO [$ i]} ตัวเรียกในตัวแสดงสแต็กการโทรปัจจุบันโดยใช้ข้อมูลนี้

[ที่มา: คู่มือทุบตี]


วิธีนี้ใช้ได้ผลกับฉันในขณะที่คำตอบที่เลือกนั้นทำงานเป็นระยะ ๆ เท่านั้น ฉันไม่เคยเข้าใจว่าทำไมมันถึงได้ผลในบางครั้งและบางครั้งก็ไม่ใช่คนอื่น ๆ
Jim2B

17

เพื่อความละเอียดและเพื่อผู้ค้นหานี่คือสิ่งที่พวกเขาทำ ... มันเป็นวิกิชุมชนดังนั้นอย่าลังเลที่จะเพิ่มการเทียบเท่าของเชลล์อื่น ๆ (แน่นอนว่า $ BASH_SOURCE จะแตกต่างกัน)

test.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

$

zsh

$ ./test2.sh
./test.sh
./test.sh
./test.sh

$ zsh test.sh

echo
test.sh

$

1
ผมไม่เข้าใจว่าทำไมcalled=$_; echo $called; echo $_? พิมพ์นี้จะไม่$_สองครั้ง?
Ciro Santilli 事件改造中心法轮功六四事件

5
@CiroSantilli: ไม่เสมออ่านคู่มือ Bashใน$_พารามิเตอร์พิเศษ: "เมื่อเริ่มต้นเชลล์ตั้งชื่อพา ธ สัมบูรณ์ที่ใช้ในการเรียกเปลือกหรือสคริปต์เปลือกที่จะดำเนินการตามที่ส่งผ่านในสภาพแวดล้อมหรือรายการอาร์กิวเมนต์ต่อจากนั้นขยายไปที่สุดท้าย อาร์กิวเมนต์ไปที่คำสั่งก่อนหน้าหลังจากการขยายนอกจากนี้ยังตั้งค่าเป็นชื่อพา ธ แบบเต็มที่ใช้เพื่อเรียกใช้คำสั่งแต่ละคำสั่งที่ดำเนินการและวางไว้ในสภาพแวดล้อมที่ส่งออกไปยังคำสั่งนั้นเมื่อตรวจสอบเมลพารามิเตอร์นี้จะเก็บชื่อไฟล์
Adam Rosenfield

ปัญหานี้เป็นไฟล์ที่มามีส่วนหัว#! /bin/shซึ่งทำให้ไร้ประโยชน์แหล่งที่มา ที่จะเริ่มต้นอินสแตนซ์ใหม่ของ/bin/shตั้งค่าตัวแปรแล้วออกจากอินสแตนซ์นั้นโดยปล่อยอินสแตนซ์การเรียกไม่เปลี่ยนแปลง
JamesThomasMoon1979

2
@ JamesThomasMoon1979: คุณกำลังพูดถึงอะไร? สิ่งใดที่เริ่มต้นด้วย#เชลล์สคริปต์คือความคิดเห็น  #!(shebang) มีความหมายพิเศษเฉพาะบรรทัดแรกของสคริปต์ที่ถูกเรียกใช้   ในฐานะที่เป็นบรรทัดแรกของไฟล์ที่มีที่มามันเป็นเพียงความคิดเห็น
สกอตต์

13

สิ่งนี้ใช้ได้สำหรับฉันในการทุบตี, ประ, ksh และ zsh:

if test -n "$BASH" ; then script=$BASH_SOURCE
elif test -n "$TMOUT"; then script=${.sh.file}
elif test -n "$ZSH_NAME" ; then script=${(%):-%x}
elif test ${0##*/} = dash; then x=$(lsof -p $$ -Fn0 | tail -1); script=${x#n}
else script=$0
fi

echo $script

เอาต์พุตสำหรับเชลล์เหล่านี้:

BASH source: ./myscript
ZSH source: ./myscript
KSH source: /home/pbrannan/git/theme/src/theme/web/myscript
DASH source: /home/pbrannan/git/theme/src/theme/web/myscript
BASH: ./myscript
ZSH: ./myscript
KSH: /home/pbrannan/git/theme/src/theme/web/myscript
DASH: ./myscript

ฉันพยายามทำให้มันทำงานได้กับ csh / tcsh แต่มันยากเกินไป ฉันกำลังติด POSIX


1

ฉันรู้สึกสับสนเล็กน้อยจากคำตอบของวิกิชุมชน (จาก Shawn J. Goff) ดังนั้นฉันจึงเขียนสคริปต์เพื่อแยกแยะสิ่งต่างๆ เกี่ยวกับ$_ฉันพบนี้: การใช้_เป็นตัวแปรสภาพแวดล้อมส่งผ่านไปยังคำสั่ง มันเป็นตัวแปรสภาพแวดล้อมดังนั้นจึงง่ายต่อการทดสอบค่าของมันอย่างไม่ถูกต้อง

ด้านล่างเป็นสคริปต์จากนั้นจะแสดงผลลัพธ์ พวกเขายังอยู่ในส่วนสำคัญนี้

test-shell-default-variables.sh

#!/bin/bash

# test-shell-default-variables.sh

# Usage examples (you might want to `sudo apt install zsh ksh`):
#
#  ./test-shell-default-variables.sh dash bash
#  ./test-shell-default-variables.sh dash bash zsh ksh
#  ./test-shell-default-variables.sh dash bash zsh ksh | less -R

# `-R` in `less -R` to have less pass escape sequences directly to the terminal
# so we have colors.


# The "invoking with name `sh`" tests are commented because for every shell I
# tested (dash, bash, zsh and ksh), the output was the same as that of dash.

# The `test_expression` function also work with expansion changes. You can try
# lines like `test_expression '{BASH_SOURCE:-$0}'`.

echolor() {
    echo -e "\e[1;36m$@\e[0m"
}

tell_file() {
    echo File \`"$1"\` is:
    echo \`\`\`
    cat "$1"
    echo \`\`\`
    echo
}

SHELL_ARRAY=("$@")

test_command() {
    for shell in "${SHELL_ARRAY[@]}"
    do
        prepare "$shell"
        cmd="$(eval echo $1)"
        # echo "cmd: $cmd"
        printf '%-4s: ' "$shell"
        { env -i $cmd 2>&1 1>&3 | sed 's/^/[err]/'; } 3>&1
        teardown
    done
    echo
}

prepare () {
    shell="$1"
    PATH="$PWD/$shell/sh:$PATH"
}

teardown() {
    PATH="${PATH#*:}"
}


###
### prepare
###
for shell in "${SHELL_ARRAY[@]}"
do
    mkdir "$shell"
    ln -sT "/bin/$shell" "$shell/sh"
done

echo > printer.sh
echo '. ./printer.sh' > sourcer.sh
rm linked.sh &>/dev/null; ln -sT "printer.sh" "linked.sh"

tell_file sourcer.sh

###
### run
###
test_expression() {
    local expr="$1"

    # prepare
    echo "echo $expr" > printer.sh
    tell_file printer.sh

    # run
    cmd='$shell ./printer.sh'
    echolor "\`$cmd\` (simple invocation) ($expr):"
    test_command "$cmd"

    # cmd='sh ./printer.sh'
    # echolor "\`$cmd\` (when executable name is \`sh\`) ($expr):"
    # test_command "$cmd"

    cmd='$shell ./sourcer.sh'
    echolor "\`$cmd\` (via sourcing) ($expr):"
    test_command "$cmd"

    # cmd='sh ./sourcer.sh'
    # echolor "\`$cmd\` (via sourcing, when name is \`sh\`) ($expr):"
    # test_command "$cmd"

    cmd='$shell ./linked.sh'
    echolor "\`$cmd\` (via symlink) ($expr):"
    test_command "$cmd"

    # cmd='sh ./linked.sh'
    # echolor "\`$cmd\` (via symlink, when name is \`sh\`) ($expr):"
    # test_command "$cmd"

    echolor "------------------------------------------"
    echo
}

test_expression '$BASH_SOURCE'
test_expression '$0'
test_expression '$(/bin/true x y; true a b c; echo $_)' # Rq: true is a builtin
test_expression '$_'

###
### teardown
###
for shell in "${SHELL_ARRAY[@]}"
do
    rm "$shell/sh"
    rm -d "$shell"
done

rm sourcer.sh
rm linked.sh
rm printer.sh

ผลผลิตของ ./test-shell-default-variables.sh {da,ba,z,k}sh

File `sourcer.sh` is:
```
. ./printer.sh
```

File `printer.sh` is:
```
echo $BASH_SOURCE
```

`$shell ./printer.sh` (simple invocation) ($BASH_SOURCE):
dash: 
bash: ./printer.sh
zsh : 
ksh : 

`$shell ./sourcer.sh` (via sourcing) ($BASH_SOURCE):
dash: 
bash: ./printer.sh
zsh : 
ksh : 

`$shell ./linked.sh` (via symlink) ($BASH_SOURCE):
dash: 
bash: ./linked.sh
zsh : 
ksh : 

------------------------------------------

File `printer.sh` is:
```
echo $0
```

`$shell ./printer.sh` (simple invocation) ($0):
dash: ./printer.sh
bash: ./printer.sh
zsh : ./printer.sh
ksh : ./printer.sh

`$shell ./sourcer.sh` (via sourcing) ($0):
dash: ./sourcer.sh
bash: ./sourcer.sh
zsh : ./printer.sh
ksh : ./sourcer.sh

`$shell ./linked.sh` (via symlink) ($0):
dash: ./linked.sh
bash: ./linked.sh
zsh : ./linked.sh
ksh : ./linked.sh

------------------------------------------

File `printer.sh` is:
```
echo $(/bin/true x y; true a b c; echo $_)
```

`$shell ./printer.sh` (simple invocation) ($(/bin/true x y; true a b c; echo $_)):
dash: 
bash: c
zsh : c
ksh : 

`$shell ./sourcer.sh` (via sourcing) ($(/bin/true x y; true a b c; echo $_)):
dash: 
bash: c
zsh : c
ksh : 

`$shell ./linked.sh` (via symlink) ($(/bin/true x y; true a b c; echo $_)):
dash: 
bash: c
zsh : c
ksh : 

------------------------------------------

File `printer.sh` is:
```
echo $_
```

`$shell ./printer.sh` (simple invocation) ($_):
dash: 
bash: bash
zsh : 
ksh : 

`$shell ./sourcer.sh` (via sourcing) ($_):
dash: 
bash: bash
zsh : ./printer.sh
ksh : 

`$shell ./linked.sh` (via symlink) ($_):
dash: 
bash: bash
zsh : 
ksh : 

------------------------------------------

เราเรียนรู้อะไร

$BASH_SOURCE

  • $BASH_SOURCE ทำงานในทุบตีและทุบตีเท่านั้น
  • ข้อแตกต่างเพียงอย่างเดียว$0คือเมื่อไฟล์ปัจจุบันถูกจัดหาโดยไฟล์อื่น ในกรณีนั้น$BASH_PROFILEมีชื่อของไฟล์ที่มามากกว่าของไฟล์ที่มา

$0

  • ใน zsh $0มีค่าเช่นเดียวกับ$BASH_SOURCEในทุบตี

$_

  • $_ ถูกทิ้งไว้โดยไม่มีการแตะต้องโดยเส้นประและ ksh
  • ใน bash และ zsh $_สลายตัวไปยังอาร์กิวเมนต์สุดท้ายของการโทรล่าสุด
  • bash เริ่มต้น$_เป็น "bash"
  • zsh $_ไม่ถูกแตะต้อง (เมื่อทำการจัดหามันเป็นเพียงผลลัพธ์ของกฎ "อาร์กิวเมนต์สุดท้าย")

symlinks

  • เมื่อสคริปต์ถูกเรียกผ่าน symlink จะไม่มีตัวแปรใดที่มีการอ้างอิงถึงปลายทางของลิงก์เพียงชื่อเท่านั้น

ksh

  • เกี่ยวกับการทดสอบเหล่านั้น ksh ทำงานเหมือนเส้นประ

ดวลจุดโทษ

  • เมื่อ bash หรือ zsh ถูกเรียกผ่าน symlink ชื่อshเกี่ยวกับการทดสอบเหล่านั้นมันจะทำงานเหมือนเส้นประ


0

เพื่อให้สคริปต์ของคุณใช้ได้ทั้ง bash และ zsh แทนการใช้ if statement คุณสามารถเขียน${BASH_SOURCE[0]:-${(%):-%x}}ได้ง่าย ค่าผลลัพธ์จะถูกนำมาจากBASH_SOURCE[0]เมื่อมีการกำหนดและ${(%):-%x}}เมื่อไม่ได้กำหนด BASH_SOURCE [0]


0

tl; dr script=$(readlink -e -- "${BASH_SOURCE}") (สำหรับ bashชัด ๆ )


$BASH_SOURCE กรณีทดสอบ

ไฟล์ที่กำหนด /tmp/source1.sh

echo '$BASH_SOURCE '"(${BASH_SOURCE})"
echo 'readlink -e $BASH_SOURCE'\
     "($(readlink -e -- "${BASH_SOURCE}"))"

source ไฟล์ในลักษณะที่แตกต่าง

source จาก /tmp

$> cd /tmp

$> source source1.sh
$BASH_SOURCE (source1.sh)
readlink -e $BASH_SOURCE (/tmp/source1.sh)

$> source ./source1.sh
$BASH_SOURCE (./source1.sh)
readlink -e $BASH_SOURCE (/tmp/source1.sh)

$> source /tmp/source1.sh
$BASH_SOURCE (/tmp/source1.sh)
readlink -e $BASH_SOURCE (/tmp/source1.sh)

source จาก /

cd /
$> source /tmp/source1.sh
$0 (bash)
$BASH_SOURCE (/tmp/source1.sh)
readlink -e $BASH_SOURCE (/tmp/source1.sh)

sourceจากเส้นทางญาติที่แตกต่างกัน/tmp/aและ/var

$> cd /tmp/a

$> source ../source1.sh
$BASH_SOURCE (../source1.sh)
readlink -e $BASH_SOURCE (/tmp/source1.sh)

$> cd /var

$> source ../tmp/source1.sh
$BASH_SOURCE (../tmp/source1.sh)
readlink -e $BASH_SOURCE (/tmp/source1.sh)

เกี่ยวกับ $0

ในทุกกรณีหากสคริปต์มีคำสั่งเพิ่ม

echo '$0 '"(${0})"

จากนั้นsourceสคริปต์จะพิมพ์ออกมาเสมอ

$0 (bash)

อย่างไรก็ตามหากสคริปต์ทำงานเช่น

$> bash /tmp/source1.sh

จากนั้นจะเป็นค่าสตริง$0/tmp/source1.sh

$0 (/tmp/source1.sh)
$BASH_SOURCE (/tmp/source1.sh)
readlink -e $BASH_SOURCE (/tmp/source1.sh)

0

คำตอบนี้อธิบายถึงวิธีการlsofและ grep มายากลเวทเป็นสิ่งเดียวที่ดูเหมือนจะมีโอกาสในการทำงานกับไฟล์ที่มาซ้อนกันภายใต้ tcsh:

/usr/sbin/lsof +p $$ | grep -oE /.\*source_me.tcsh

-2
wdir="$PWD"; [ "$PWD" = "/" ] && wdir=""
case "$0" in
  /*) scriptdir="${0%/*}";;
  *) scriptdir="$wdir/${0#./}"; scriptdir="${scriptdir%/*}";;
esac
echo "$scriptdir"

บางทีนี่อาจจะไม่ทำงานกับ symlink หรือไฟล์ที่มา แต่ใช้ได้กับไฟล์ปกติ นำมาอ้างอิงไปๆมาๆ @kenorb ไม่มีชื่อเล่น readlink, BASH_SOURCE


1
มีการอธิบายในคำถามที่$0ให้ข้อมูลคุณเกี่ยวกับสคริปต์ที่กำลังทำงานอยู่ไม่ใช่สคริปต์ที่มา
สกอตต์

-3

ที่จริงแล้ว "dirname $ 0" จะพาคุณไปยังสคริปต์ แต่คุณต้องตีความมันเล็กน้อย:

$ cat bash0
#!/bin/bash
echo \$0=$0
dirname $0
$ bash0    # "." appears in PATH right now.
$0=./bash0
.
$ ./bash0
$0=./bash0
.
$ $PWD/bash0
$0=/home/00/bediger/src/ksh/bash0
/home/00/bediger/src/ksh
$ $PWD/../ksh/bash0
$0=/home/00/bediger/src/ksh/../ksh/bash0
/home/00/bediger/src/ksh/../ksh
$ ../ksh/bash0
$0=../ksh/bash0
../ksh

คุณต้องเตรียมรับมือ "" เป็นชื่อไดเรกทอรีภายใต้สถานการณ์ทั่วไปบางอย่าง ฉันจะทดลองสักหน่อยเพราะฉันจำได้ว่าชื่อ dirname ในตัวเพื่อ ksh ทำสิ่งต่าง ๆ เล็กน้อยเมื่อ "" ปรากฏขึ้นใน PATH


4
นี่คือสคริปต์ที่มาไม่ใช่สคริปต์ที่ดำเนินการ $0เพียงแค่มี "ทุบตี" สำหรับเปลือกโต้ตอบและนั่นคือทั้งหมดที่สคริปต์ที่มาเห็น
Cascabel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.