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:
# A file with three trailing newlines.
file=$'/tmp/evil\n\n\n'
# Add an 'x' so we can tell where $file's newlines end and basename's begin.
file_x="$(basename -- "$file"; printf x)"
# Strip off two trailing characters: the 'x' added by us and the newline added by basename.
base="${file_x%??}"
Alternatifnya adalah menggunakan ${file##*/}
, yang lebih mudah tetapi memiliki bug sendiri. Secara khusus, itu salah dalam kasus di mana $file
adalah /
atau foo/
.