basename
не приймає список шляхів (не кажучи вже про один відмежований рядками), це займає самотній шлях (за бажанням слід суфікс для видалення).
Додатково, при використанні команди (як echo
) у зворотній стороні, оболонка виводить дані команди, розбиває її на "слова", відокремлені пробілами (в основному пропуски, вкладки та нові рядки, але ви можете змінити її $IFS
), розширює будь-які знайдені маски і передає результат у іншу команду ( basename
в цьому випадку). У результаті з'являються нові рядки в echo
Вихідні дані розглядаються як просто більше пробілів між словами, які не передаються basename
зовсім. Отже, ця команда:
basename `echo -e '/foo/bar \n /food/baz \n /oof/rab'`
еквівалентно:
basename "/foo/bar" "/food/baz" "/oof/rab"
... і, мабуть, коли basename
отримує три аргументи, як це, він виводить базову назву кожного аргументу окремо. Сторінка для basename
не документує цю поведінку, тому, якщо що-небудь, це помилка, що в цьому випадку не дає помилки.
Аналогічно ця команда:
basename `echo -e '/foo/bar \n /food/baz'`
еквівалентно
basename "/foo/bar" "/food/baz"
... але в цьому випадку basename
Поведінка визначається і зовсім інша - вона бере базову назву першого аргументу, видаляє другий аргумент з її кінця (якщо він збігається) і друкує результат. "бар" не закінчується на "/ food / baz", тому він просто друкує "бар".
Також, echo -e
дивно непереносимий (навіть між різними версіями OS X!). Нижче я використовував bash's $' '
Строковий формат, щоб отримати трансляційні послідовності.
Якщо потрібно надрукувати базові назви шляхів, розділених символом нового рядка, використовуйте цикл для запуску basename
на кожному окремо:
while read -r filepath; do
basename "$filepath"
done <<< $'/foo/bar \n /food/baz'
Або просто використовуйте sed
видалити до першого "/" у кожному рядку:
echo $'/foo/bar \n /food/baz \n /oof/rab' | sed 's@^.*/@@'
xargs -n 1
замість циклу.