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
получает три аргумента, как это, он печатает базовое имя каждого аргумента отдельно. Страница man для basename
не документирует это поведение, поэтому в любом случае это ошибка, которая не выдает ошибку в этом случае.
Аналогично, эта команда:
basename `echo -e '/foo/bar \n /food/baz'`
эквивалентно
basename "/foo/bar" "/food/baz"
... но в этом случае поведение basename
определено и совершенно иное - оно берет базовое имя первого аргумента, удаляет второй аргумент с его конца (если он совпадает) и печатает результат. "bar" не заканчивается на «/food/baz», поэтому он просто печатает "bar".
Кроме того, echo -e
странно непереносима (даже между различными версиями OS X!). Ниже, я использовал Баш в $' '
строки , чтобы избежать последовательностей переведены.
Если вы хотите напечатать базовые имена списка путей, разделенных новой строкой, используйте цикл для запуска 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@^.*/@@'