เหตุใดแบ็กสแลชจึงรวมอยู่ในเชลล์สคริปต์นี้


21

ในสำเนาconda.shสคริปต์ของฉันฉันเห็นบรรทัดต่อไปนี้:

if [ -n "${_CE_CONDA}" ] && [ -n "${WINDIR+x}" ]; then
    SYSP=$(\dirname "${CONDA_EXE}")
else
    SYSP=$(\dirname "${CONDA_EXE}")
    SYSP=$(\dirname "${SYSP}")
fi

ผมอยากรู้ว่าทำไมถึงมีการทับขวาในด้านหน้าในd dirnameฉันไม่เชื่อว่ามีความจำเป็น การใช้แบ็กสแลชนี้ปรากฏในที่อื่นในไฟล์ต้นฉบับ มีเหตุผลในการทำสิ่งนี้ที่ฉันหายไปหรือไม่?


คำตอบ:


30

แบ็กสแลชจะระงับการขยายนามแฝงนั่นคือมันรันคำสั่งเดิมและทำให้แน่ใจว่าเวอร์ชันนามแฝงจะไม่ทำงาน สคริปสามารถทำงานได้โดยไม่รู้ตัวกับการขยายตัวนามแฝงเมื่อระบบได้มีการกำหนดshopt -s expand_aliases(ทุบตีเท่านั้น) sourceหรือถ้ามันจะถูกดำเนินการโดยใช้

./conda.sh          # usually no alias expansion (unless `shopt -s expand_aliases` in BASH)
source ./conda.sh   # alias expansion
. ./conda.sh        # alias expansion

ผู้ดูแลระบบบางคนชอบที่จะใส่แบ็กสแลชในทุกสิ่งเพื่อป้องกันผลข้างเคียงของนามแฝงในกรณีที่มีการใช้นามแฝงโดยไม่ได้ตั้งใจที่อื่นและนามแฝงจะขยายตามที่อธิบายไว้ก่อนหน้านี้ ตัวอย่างเช่นหากระบบได้ตั้งค่าไว้ที่alias dirname='dirname -z'ใดที่หนึ่งและเงื่อนไขอนุญาตให้ขยายนามแฝงได้สคริปต์ที่พยายามเรียก dirname จะโทรdirname -zแทนขออภัยซึ่งไม่ใช่สคริปต์ที่ตั้งใจไว้

หากมีความมั่นใจว่านามแฝงดังกล่าวไม่มีอยู่เราสามารถลบเครื่องหมายแบ็กสแลชทั้งหมดและควรจะทำงานได้ดี

อีกวิธีหนึ่งสามารถใช้commandแทนเวอร์ชันแบ็กสแลชเพื่อระงับนามแฝง ดังนั้นแทนที่จะใช้\dirnameอย่างใดอย่างหนึ่งcommand dirnameซึ่งอาจดูอ่านง่ายขึ้น (สำหรับคำสั่งในตัวเช่นcdเดียวควรใช้builtinแทน) ฉันชอบสิ่งนี้แทนเพราะมันยังข้ามฟังก์ชันที่มีชื่อเดียวกันและชื่อแทนใด ๆ


1
นอกจากนี้ยังเป็นที่น่าสังเกตว่าจะunalias -aลบนามแฝงทั้งหมด
Centimane

19
@Centimane ใช่ แต่ต้องแน่ใจว่าได้ทำ\unalias -aเพื่อระงับการขยายนามแฝง
Ben C

ดูแลระบบสามารถเขียนได้เช่นกัน/usr/bin/dirname?
RonJohn

@ RonJohn ใช่เขาสามารถมีได้ในกรณีนี้โดยเฉพาะ อย่างไรก็ตามสำหรับบางโปรแกรมการกระจายที่แตกต่างกันวางไว้ในไดเรกทอรีที่แตกต่างกัน ตัวอย่างหนึ่งที่นึกถึงคือ/bin/edUbuntu และ/usr/bin/edCentOS การใส่เส้นทางแบบเต็มทำให้สคริปต์พกพาได้น้อยลง
doneal24

@ doneal24 แล้วจะมีอะไรที่คล้ายกันDIRNAME=$(which dirname)บ้างเนื่องจากwhichไม่เห็นชื่อแทน?
RonJohn

20

หากconda.shเป็นไฟล์ที่มีความหมายว่าจะต้องจัดหาจากนั้นแบ็กสแลชนั้นใช้สำหรับการข้ามนามแฝง โดยทั่วไปแล้วทุบตีจะปิดใช้งานการขยายนามแฝงสำหรับการดำเนินการสคริปต์ แต่สำหรับไฟล์ที่มาซึ่งอาจทำงานในเชลล์แบบโต้ตอบนั่นไม่ใช่กรณี ดังนั้นเพียงแค่dirnameอาจใช้นามแฝงชื่อdirnameแต่จะข้ามการขยายตัวนามแฝงและเรียกใช้ฟังก์ชันหรือคำสั่งการตั้งชื่อ\dirname dirname(ไม่ใช่แบ็กสแลชเพียงอย่างเดียวการอ้างใด ๆ จะทำ)


5
command dirnameหรือ
Kusalananda

7
( \command dirnameในกรณีที่มีคนทำนามแฝงcommandเช่นกัน): |
muru

เหตุใดจึงข้ามนามแฝง ฟังก์ชั่นนี้เป็นกรณีพิเศษของบางสิ่งบางอย่างหรือต้องฮาร์ดโค้ดลงในทุบตี (เช่นแฮ็ค)?
extremeaxe5 5

@ Extremeaxe5 bash ไม่ได้ทำการขยายนามแฝงถ้า (ส่วนใดส่วนหนึ่งของ) คำนั้นถูกยกมา
muru

1
@ Extremeaxe5 ถ้าคุณถามว่าทำไมถึงมีฟีเจอร์นี้อยู่เลยฉันไม่รู้ มันมีอยู่ในมาตรฐาน POSIXแต่ "คำชื่อคำสั่ง [ ... ] จะได้รับการตรวจสอบเพื่อตรวจสอบว่าเป็นunquotedชื่อนามแฝงถูกต้อง"
Muru
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.