Saya mencoba shellcheck .
Saya punya sesuatu seperti itu
basename "${OPENSSL}"
dan saya mendapatkan saran berikut
Use parameter expansion instead, such as ${var##*/}.
Dari sudut pandang praktis saya tidak melihat perbedaan
$ export OPENSSL=/opt/local/bin/openssl
$ basename ${OPENSSL}
openssl
$ echo ${OPENSSL##*/}
openssl
Karena basename
ada dalam spesifikasi POSIX , saya tidak punya alasan mengapa itu harus menjadi praktik terbaik. Ada petunjuk?
csh
. Saya kiracsh
itu bukan POSIX.Jawaban:
Ini bukan tentang efisiensi - ini tentang kebenaran.
basename
menggunakan baris baru untuk membatasi nama file yang dicetaknya. Dalam kasus yang biasa ketika Anda hanya melewatkan satu nama file, itu menambahkan baris tambahan ke outputnya. Karena nama file mungkin mengandung baris baru sendiri, ini membuatnya sulit untuk menangani nama file ini dengan benar.Ini lebih rumit oleh fakta bahwa orang biasanya menggunakan
basename
seperti ini:"$(basename "$file")"
. Ini membuat segalanya semakin sulit, karena semua$(command)
strip mengikuti garis baru . Pertimbangkan kasus tidak terduga yang berakhir dengan baris baru. Kemudian akan menambahkan baris baru tambahan, tetapi akan menghapus kedua baris baru, membuat Anda dengan nama file yang salah.command
$file
basename
"$(basename "$file")"
Masalah lain dengan
basename
adalah bahwa jika$file
diawali dengan-
(minus alias minus), itu akan ditafsirkan sebagai opsi. Yang ini mudah diperbaiki:$(basename -- "$file")
Cara penggunaan yang kuat
basename
adalah ini:Alternatifnya adalah menggunakan
${file##*/}
, yang lebih mudah tetapi memiliki bug sendiri. Secara khusus, itu salah dalam kasus di mana$file
adalah/
ataufoo/
.sumber
$file
itufoo/
? Bagaimana jika itu/
?basename
pendekatannya lebih baik, sama hebohnya. Alternatif terbaik yang bisa saya temukan adalah${${${file}%%/#}##*/}
dan[[ $file =~ "([^/]*)/*$" ]] && printf "%s" $match[1]
, keduanya zsh-specific dan tidak ada yang menangani/
dengan benar.Garis-garis yang relevan di
shellcheck
's kode sumber adalah:Tidak ada penjelasan yang diberikan secara eksplisit tetapi berdasarkan nama fungsi (
checkNeedlessCommands
) sepertinya @jordanm cukup benar dan ini menyarankan Anda menghindari forking proses baru.sumber
dirname
,basename
,readlink
Dll (terima kasih @Marco - ini dikoreksi) dapat membuat masalah portabilitas ketika keamanan menjadi penting (yang membutuhkan keamanan jalan). Banyak sistem (seperti Fedora Linux) menempatkannya di/bin
sedangkan yang lain (seperti Mac OSX) menempatkannya di/usr/bin
. Lalu ada Bash di Windows, misalnya cygwin, msys, dan lainnya.Selalu lebih baik untuk tetap menjadi Bash murni, jika memungkinkan.(per komentar @Marco)BTW, terima kasih atas pointer ke shellcheck, saya belum pernah melihat itu sebelumnya.
sumber
dirname
sama sekali. 3) Utilitas inti dasar harus berada di PATH, di mana pun disimpan. Saya belum melihat sistem di manabasename
tidak ada di PATH. 4) Dengan asumsi bash tersedia adalah masalah portabilitas. Itu selalu lebih baik untuk menjauh dari bash dan menggunakan shell POSIX ketika portabilitas diperlukan.posix
dan tidakbash
. Saya gagal menemukan indikator bahwa OP memerlukan solusi bash. Pernyataan Anda "Selalu lebih baik untuk tetap murni Bash" benar-benar salah, maaf.