在 bash 中提取没有路径和扩展名的文件基名[重复]
- 2024-10-23 08:47:00
- admin 原创
- 60
问题描述:
给定如下文件名:
/the/path/foo.txt
bar.txt
我希望得到:
foo
bar
这为什么不起作用?
#!/bin/bash
fullfile=$1
fname=$(basename $fullfile)
fbname=${fname%.*}
echo $fbname
正确的做法是什么?
解决方案 1:
您不必调用外部basename
命令。相反,您可以使用以下命令:
$ s=/the/path/foo.txt
$ echo "${s##*/}"
foo.txt
$ s=${s##*/}
$ echo "${s%.txt}"
foo
$ echo "${s%.*}"
foo
请注意,此解决方案应适用于所有最近的(2004 年后)POSIX兼容 shell,(例如,,,bash
等等)。dash
`ksh`
来源:Shell 命令语言 2.6.2 参数扩展
有关 bash 字符串操作的更多信息: http://tldp.org/LDP/LG/issue18/bash.html
解决方案 2:
basename命令有两种不同的调用方式;一种是只指定路径,在这种情况下,它会给出最后一个组件;另一种是,你还会给出一个后缀,它会删除这个后缀。因此,你可以使用 basename 的第二次调用来简化示例代码。另外,请注意正确引用以下内容:
fbname=$(基本名称“$1”.txt)
回显“$fbname”
解决方案 3:
基本名称和剪切的组合可以很好地工作,即使在双结尾的情况下也是如此.tar.gz
:
fbname=$(basename "$fullfile" | cut -d. -f1)
如果这个解决方案需要的算术能力比 Bash 参数扩展更少,那将会很有趣。
解决方案 4:
以下是一些要点:
$(basename "${s%.*}")
$(basename "${s}" ".${s##*.}")
我需要这个,和 bongbang 和 w4etwetewtwet 要求的一样。
例子:
$ s=/the/path/foo.txt
$ echo "$(basename "${s%.*}")"
foo
$ echo "$(basename "${s}" ".${s##*.}")"
foo
解决方案 5:
纯粹的bash
,没有basename
,没有变量杂耍。设置一个字符串并echo
:
p=/the/path/foo.txt
echo "${p//+(*/|.*)}"
输出:
foo
注意:bash
extglob选项必须为“on”(Ubuntu默认将extglob设置为“on”),如果不是,请执行以下操作:
shopt -s extglob
走过${p//+(*/|.*)}
:
${p
——以$p开头。//
替换下列模式的每个实例。+(
匹配括号中的一个或多个模式列表(即直到下面的第 7 项)。第一个模式:
*/
匹配文字“/
”字符之前的任何内容。模式分隔符
|
,在本例中起到逻辑或的作用。第二种模式:
.*
匹配文字“.
”之后的任何内容 - 也就是说,bash
“.
”中的只是一个句点字符,而不是 正则表达式点。)
结束模式列表。}
结束参数扩展。对于字符串替换,通常会有另一个/
there,后面跟着替换字符串。但是由于没有/
there,匹配的模式将被替换为空;这会删除匹配项。
相关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
解决方案 6:
这是获取文件名或扩展名的另一种(更复杂)方法,首先使用命令rev
反转文件路径,从第一个剪切.
,然后再次反转文件路径,如下所示:
filename=`rev <<< "$1" | cut -d"." -f2- | rev`
fileext=`rev <<< "$1" | cut -d"." -f1 | rev`
解决方案 7:
如果您想要更好地使用 Windows 文件路径(在 Cygwin 下),您也可以尝试以下操作:
fname=${fullfile##*[/|\\]}
当在 Windows 上使用 BaSH 时,这将考虑反斜杠分隔符。
解决方案 8:
这只是我想到提取扩展的另一种方法,使用此线程中的帖子和我更熟悉的小型知识库。
ext="$(rev <<< "$(cut -f "1" -d "." <<< "$(rev <<< "file.docx")")")"
注意:请对我使用引号的方式提出建议;它对我有用,但我可能忽略了它们的正确使用(我可能使用了太多)。
解决方案 9:
使用 basename 命令。它的手册页在这里: http ://unixhelp.ed.ac.uk/CGI/man-cgi?basename
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件