Учитывая такие имена файлов, как:
/the/path/foo.txt
bar.txt
я надеюсь получить:
foo
bar
Почему это не работает?
#!/bin/bash
fullfile=$1
fname=$(basename $fullfile)
fbname=${fname%.*}
echo $fbname
Как правильно это сделать?
Вам не нужно вызывать внешнюю команду basename
. Вместо этого вы можете использовать следующие команды:
$ s=/the/path/foo.txt
$ echo ${s##*/}
foo.txt
$ s=${s##*/}
$ echo ${s%.txt}
foo
$ echo ${s%.*}
foo
Обратите внимание, что это решение должно работать во всех последних (после 2004 года) POSIX совместимых оболочках (например, bash
, dash
, ksh
и т.д.).
Источник: Shell Command Language 2.6.2 Parameter Expansion
Подробнее о манипуляциях со строками в bash: http://tldp.org/LDP/LG/issue18/bash.html
Команда basename имеет два различных обращения; в одном случае вы указываете только путь, и в этом случае она выдает последний компонент, а в другом вы также указываете суффикс, который она удалит. Таким образом, вы можете упростить код вашего примера, используя второе обращение к basename. Кроме того, следите за правильным цитированием:
fbname=$(basename "$1" .txt) echo "$fbname"
Сочетание basename и режут отлично работает, даже в случае двойной финал как.tar.gz`:
fbname=$(basename "$fullfile" | cut -d. -f1)
Было бы интересно, если это решение требует меньше энергии, чем арифметические разложения по параметру Баш.
Чисто Баш
, нет файлов, нет переменной жонглирование. Задать строку и Эхо
:
s=/the/path/foo.txt
echo ${s//+(*\/|.*)}
Выход:
foo
Примечание: Баш
extglob опция должна быть "дальше", (Убунту наборы extglob "и дальше" по умолчанию), если это'ов нет, то:
shopt -s extglob
Прогулка по ${ы//+(*\/|.*)}
:
${ы
, начиная с ы$.*\/
все матчи до буквального "в/в
" Шар. |
, который в данном случае действует как логическое и..*
матчи ничего после буквального и".
&мне-то есть, в баш
в ".
" это просто чар период, и не регулярное выражение точка.)
конец шаблон списка.}
конец разложения по параметру. Со строкой замены, там'ы, как правило, еще /
там, сопровождается строкой замены. Но поскольку там's нет /
там, паттерны заменяются ничем; это удаляет играм.Соответствующих человеку Баш фон:
${параметр/шаблон/строка} замена рисунка. Модель расширена для производства ПЭТ‐ крачка просто как расширение пути. Параметр расширяется и самый длинный матч рисунком на его значение заменяется строка. Если шаблон начинается с /, все матчи шаблона заменить строку. Обычно только первый матч заменить. Если шаблон начинается с #, он должен соответствовать в начале‐ нинг расширенного значения параметра. Если шаблон начинается с %, оно должно соответствовать по завершении расширенного значения параметра. если строка имеет значение null, спички из массива удаляются и / Фоль‐ мычание шаблон может быть опущен. Если параметр @ или , открытый операции stitution применяется для каждого позиционного параметра в В свою очередь, и расширение результирующий список. Если параметр В переменной массива, индексного С @ или , замена операция применяется к каждому элементу массива, в свою очередь, и расширение результирующий список.
если параметр оболочки extglob включается с помощью shopt строение, несколько расширенная шаблону операторы признали. В следующем описание, шаблон-список-это список из одного или более шаблонов, разделенных в |. Составные шаблоны могут быть сформированы с использованием одного или более из следую‐ мычание суб-моделей:
?(шаблон-список) соответствует нулю или одному экземпляру данной модели *(выкройка-лист) соответствует нулю или более вхождений данной модели +(выкройка-лист) соответствует одному или нескольким вхождениям данной модели @(шаблон списка) У игр один из предложенных шаблонов !(шаблон-список) матчи ничего, кроме одной из моделей
Вот oneliner'ы:
$(и basename ${с%.*})
$(и basename ${ы} .${с##*.})
Я нуждался в этом, так же, как спросил bongbang и w4etwetewtwet.
Вот еще один (более сложный) способ получения либо именем или расширением, сначала используйте команды Ред.
инвертировать путь файл, вырезать из первого. а потом опять поменять путь к файлу, например:
filename=`rev <<< "$1" | cut -d"." -f2- | rev`
fileext=`rev <<< "$1" | cut -d"." -f1 | rev`
Просто альтернатива, которую я придумал для извлечения расширения, используя посты в этой теме с моей небольшой базы знаний, который был более привычен для меня.
ext="$(rev <<< "$(cut -f "1" -d "." <<< "$(rev <<< "file.docx")")")"
Примечание: пожалуйста, сообщите, что я использую цитаты; он работал для меня, но я, возможно, отсутствует что-то об их правильном использовании (я, наверное, слишком много).
Используйте команду basename. Ее руководство находится здесь: http://unixhelp.ed.ac.uk/CGI/man-cgi?basename