Nie chodzi o wydajność - chodzi o poprawność. basenameużywa znaku nowej linii do określenia nazw plików, które drukuje. W zwykłym przypadku, gdy przekazujesz tylko jedną nazwę pliku, dodaje on końcowy znak nowej linii do wyniku. Ponieważ nazwy plików mogą zawierać same znaki nowej linii, utrudnia to prawidłową obsługę tych nazw plików.
To dodatkowo komplikuje fakt, że ludzie zwykle wykorzystać basenametak: "$(basename "$file")". To sprawia, że wszystko jest jeszcze trudniejsze, ponieważ $(command)usuwa wszystkie końcowe znaki nowej linii command. Rozważ mało prawdopodobny przypadek, który $filekończy się nową linią. Następnie basenamedoda nową "$(basename "$file")"linię , ale usunie obie linie, pozostawiając niepoprawną nazwę pliku.
Innym problemem basenamejest to, że jeśli $filezaczyna się od -(myślnik aka minus), będzie to interpretowane jako opcja. Ten jest łatwy do naprawienia:$(basename -- "$file")
Solidny sposób użycia basenamejest następujący:
# 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%??}"
Alternatywą jest użycie ${file##*/}, które jest łatwiejsze, ale ma własne błędy. W szczególności jest to złe w przypadkach, gdy $filejest /lub foo/.