Извлечение имени файла без пути и расширения в bash [дубликат]
этот вопрос уже есть ответ здесь:
- извлечь имя файла и расширение в Bash 35 ответов
данные имена файлов, как эти:
/the/path/foo.txt
bar.txt
Я надеюсь получить:
foo
bar
почему это не сработает?
#!/bin/bash
fullfile=
fname=$(basename $fullfile)
fbname=${fname%.*}
echo $fbname
Как правильно это сделать?
9 ответов
на имени команда имеет два разных вызова; в одном вы указываете только путь, в этом случае он дает вам последний компонент, а в другом вы также даете суффикс, который он удалит. Таким образом, вы можете упростить свой пример кода, используя второй вызов basename. Кроме того, будьте осторожны, чтобы правильно цитировать вещи:
fbname=$(basename "" .txt) echo "$fbname"
комбинация basename и cut отлично работает, даже в случае двойного окончания, такого как .tar.gz
:
fbname=$(basename "$fullfile" | cut -d. -f1)
было бы интересно, если это решение требует меньше арифметической мощности, чем расширение параметра Bash.
чисто bash
, нет basename
, нет переменной жонглирование. Установите строку и echo
:
s=/the/path/foo.txt
echo ${s//+(*\/|.*)}
выход:
foo
Примечание:bash
extglob опция должна быть "on", (on Ubuntu это" on " по умолчанию), если это не так, сделайте:
shopt -s extglob
пешком через ${s//+(*\/|.*)}
:
-
${s
-- начинаются с $s. -
//
замените каждый экземпляр узор. -
+(
матч один или несколько на список шаблон в скобках. -
*\/
все матчи до/
. (1-й образец) -
|
или. (разделитель шаблонов.) -
.*
соответствует что-нибудь после.
. (2-й образец) -
)
конец список шаблон. -
}
параметр расширения, поскольку нет/
(который предшествует замене строки), совпадающие шаблоны удаляются.
соответствующей man bash
справочная информация:
- замена шаблона:
${parameter/pattern/string} Pattern substitution. The pattern is expanded to produce a pat‐ tern just as in pathname expansion. Parameter is expanded and the longest match of pattern against its value is replaced with string. If pattern begins with /, all matches of pattern are replaced with string. Normally only the first match is replaced. If pattern begins with #, it must match at the begin‐ ning of the expanded value of parameter. If pattern begins with %, it must match at the end of the expanded value of parameter. If string is null, matches of pattern are deleted and the / fol‐ lowing pattern may be omitted. If parameter is @ or *, the sub‐ stitution operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with @ or *, the substitution operation is applied to each member of the array in turn, and the expansion is the resultant list.
- расширенный поиск по шаблону:
If the extglob shell option is enabled using the shopt builtin, several extended pattern matching operators are recognized. In the following description, a pattern-list is a list of one or more patterns separated by a |. Composite patterns may be formed using one or more of the fol‐ lowing sub-patterns: ?(pattern-list) Matches zero or one occurrence of the given patterns *(pattern-list) Matches zero or more occurrences of the given patterns +(pattern-list) Matches one or more occurrences of the given patterns @(pattern-list) Matches one of the given patterns !(pattern-list) Matches anything except one of the given patterns
вот oneliners:
$(basename ${s%.*})
$(basename ${s} .${s##*.})
мне это было нужно, так же, как спросили bongbang и w4etwetewtwet.
вот еще один (более сложный) способ получить имя файла или расширение, сначала используйте rev
команда инвертировать путь к файлу, вырезать из первого .
а затем снова инвертируйте путь к файлу, например:
filename=`rev <<< "" | cut -d"." -f2- | rev`
fileext=`rev <<< "" | cut -d"." -f1 | rev`
Если вы хотите играть хорошо с путями файлов Windows (под Cygwin), вы также можете попробовать следующее:
fname=${fullfile##*[/|\]}
это будет учитывать разделители обратной косой черты при использовании BaSH в Windows.
просто альтернатива, которую я придумал, чтобы извлечь расширение, используя сообщения в этом потоке с моей собственной небольшой базой знаний, которая была мне более знакома.
ext="$(rev <<< "$(cut -f "1" -d "." <<< "$(rev <<< "file.docx")")")"
Примечание: пожалуйста, посоветуйте мне использовать цитаты; это сработало для меня, но я мог бы пропустить что-то по их правильному использованию (я, вероятно, использую слишком много).
используйте команду basename. Его manpage здесь:http://unixhelp.ed.ac.uk/CGI/man-cgi?basename