Đó không phải là về hiệu quả - đó là về tính đúng đắn. basename
sử dụng các dòng mới để phân định tên tệp mà nó in ra. Trong trường hợp thông thường khi bạn chỉ truyền một tên tệp, nó sẽ thêm một dòng mới vào đầu ra của nó. Vì tên tệp có thể chứa dòng mới, điều này gây khó khăn cho việc xử lý chính xác các tên tệp này.
Nó phức tạp hơn nữa bởi thực tế là mọi người thường sử dụng basename
như thế này : "$(basename "$file")"
. Điều này làm cho mọi thứ trở nên khó khăn hơn, bởi vì $(command)
dải tất cả các dòng mới từ command
. Xem xét các trường hợp không thể $file
kết thúc với một dòng mới. Sau đó basename
sẽ thêm một dòng mới, nhưng "$(basename "$file")"
sẽ loại bỏ cả hai dòng mới, để lại cho bạn một tên tệp không chính xác.
Một vấn đề khác basename
là nếu $file
bắt đầu bằng một -
dấu gạch ngang (dấu gạch ngang), nó sẽ được hiểu là một tùy chọn. Cái này rất dễ sửa:$(basename -- "$file")
Cách sử dụng mạnh mẽ basename
là:
# 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%??}"
Một cách khác là sử dụng ${file##*/}
, dễ hơn nhưng có lỗi của riêng nó. Đặc biệt, nó sai trong trường hợp $file
là /
hay foo/
.