Mengapa backslash termasuk dalam skrip shell ini?

21

Dalam salinan conda.shskrip saya, saya melihat baris-baris berikut:

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

Saya ingin tahu mengapa ada garis miring terbalik di depan yang ddi dirname. Saya tidak percaya itu perlu. Penggunaan backslash ini juga muncul di tempat lain di file sumber. Apakah ada alasan untuk melakukan ini yang saya lewatkan?

extremeaxe5
sumber

Jawaban:

30

Backslash akan menekan ekspansi alias, yaitu mengeksekusi perintah asli dan memastikan bahwa versi alias tidak berjalan. Skrip tanpa sadar dapat dijalankan dengan ekspansi alias saat sistem telah disetel shopt -s expand_aliases(khusus BASH) atau jika dijalankan menggunakan source.

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

Beberapa sysadmin suka meletakkan backslash dalam segala hal sebagai tindakan pencegahan terhadap efek samping alias, untuk berjaga-jaga kalau itu tidak sengaja alias di tempat lain dan alias akan diperluas seperti yang dijelaskan sebelumnya. Misalnya, jika sistem telah menetapkan ini di alias dirname='dirname -z'suatu tempat dan kondisi memungkinkan alias untuk diperluas, maka skrip yang mencoba memanggil dirname sayangnya akan memanggil dirname -zsebaliknya, yang bukan skrip yang dimaksudkan.

Jika ada kepastian bahwa alias tersebut tidak ada, kami dapat menghapus semua backslash dan itu akan berfungsi dengan baik.

Atau, seseorang dapat menggunakan commandalih-alih versi backslash untuk menekan alias. Jadi, alih-alih \dirname, seseorang dapat menggunakan command dirname, yang mungkin terlihat lebih mudah dibaca. (Untuk perintah bawaan seperti cd, seseorang harus menggunakan builtinsebagai gantinya). Saya lebih suka ini, karena juga memotong fungsi dengan nama yang sama dan alias.

otter.pro
sumber
1
Yang juga perlu diperhatikan adalah unalias -a, yang menghilangkan semua alias.
Centimane
19
@Centimane Ya tapi pastikan Anda lakukan \unalias -auntuk menekan ekspansi alias
Ben C
Bisakah sysadmin juga menulis /usr/bin/dirname?
RonJohn
@ RonJohn Ya dia bisa memiliki dalam kasus khusus ini. Namun, untuk beberapa program distribusi yang berbeda menempatkan mereka di direktori yang berbeda. Salah satu contoh yang muncul di pikiran adalah /bin/eddi Ubuntu vs /usr/bin/eddi CentOS. Menempatkan di jalur lengkap membuat skrip kurang portabel.
selesai24
@ doneal24 bagaimana dengan sesuatu seperti DIRNAME=$(which dirname), karena whichtidak melihat alias?
RonJohn
20

Jika conda.shfile dimaksudkan untuk bersumber, maka garis miring terbalik adalah untuk memotong alias. Bash biasanya menonaktifkan ekspansi alias untuk eksekusi skrip, tetapi untuk file bersumber, yang dapat berjalan dalam shell interaktif, bukan itu masalahnya. Jadi dirnamemungkin saja menjalankan alias bernama dirname, tetapi \dirnameakan melewatkan ekspansi alias dan menjalankan fungsi atau perintah bernama dirname. (Namun, bukan hanya garis miring terbalik, kutipan apa pun akan berlaku.)

muru
sumber
5
Atau command dirname.
Kusalananda
7
( \command dirname, kalau-kalau ada orang yang membuat alias commandjuga.): |
muru
Mengapa itu memotong alias? Apakah fungsi ini merupakan kasus khusus dari sesuatu, atau apakah harus di-hardcode menjadi bash (yaitu peretasan)?
extremeaxe5
@ extremeaxe5 bash tidak melakukan ekspansi alias jika (ada bagian dari) kata tersebut dikutip.
muru
1
@ extremeaxe5 jika Anda bertanya mengapa fitur itu ada, saya tidak tahu. Hal ini dalam standar POSIX namun: "kata nama perintah [...] harus diperiksa untuk menentukan apakah itu adalah kuotasi , berlaku nama alias"
Muru