Linux 在bash中提取没有路径和扩展名的文件基名
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2664740/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Extract file basename without path and extension in bash
提问by neversaint
Given file names like these:
给定文件名,如下所示:
/the/path/foo.txt
bar.txt
I hope to get:
我希望得到:
foo
bar
Why this doesn't work?
为什么这不起作用?
#!/bin/bash
fullfile=
fname=$(basename $fullfile)
fbname=${fname%.*}
echo $fbname
What's the right way to do it?
正确的做法是什么?
采纳答案by ghostdog74
You don't have to call the external basenamecommand. Instead, you could use the following commands:
您不必调用外部basename命令。相反,您可以使用以下命令:
$ s=/the/path/foo.txt
$ echo "${s##*/}"
foo.txt
$ s=${s##*/}
$ echo "${s%.txt}"
foo
$ echo "${s%.*}"
foo
Note that this solution should work in all recent (post 2004) POSIXcompliant shells, (e.g. bash, dash, ksh, etc.).
请注意,这个解决方案应该在所有近期的(工作后2004年)POSIX兼容的外壳(例如bash,dash,ksh等)。
Source: Shell Command Language 2.6.2 Parameter Expansion
来源:Shell Command Language 2.6.2 参数扩展
More on bash String Manipulations: http://tldp.org/LDP/LG/issue18/bash.html
更多关于 bash 字符串操作:http: //tldp.org/LDP/LG/issue18/bash.html
回答by Michael Aaron Safyan
The basenamecommand has two different invocations; in one, you specify just the path, in which case it gives you the last component, while in the other you also give a suffix that it will remove. So, you can simplify your example code by using the second invocation of basename. Also, be careful to correctly quote things:
的基名命令有两种不同调用; 在一种情况下,您只指定路径,在这种情况下,它为您提供最后一个组件,而在另一种情况下,您还提供一个后缀,它将删除。因此,您可以通过使用 basename 的第二次调用来简化示例代码。另外,请注意正确引用内容:
fbname=$(basename "" .txt) echo "$fbname"
回答by Bandicoot
Use the basename command. Its manpage is here: http://unixhelp.ed.ac.uk/CGI/man-cgi?basename
使用 basename 命令。它的手册页在这里:http: //unixhelp.ed.ac.uk/CGI/man-cgi?basename
回答by higuaro
Here is another (more complex) way of getting either the filename or extension, first use the revcommand to invert the file path, cut from the first .and then invert the file path again, like this:
这是获取文件名或扩展名的另一种(更复杂)方法,首先使用该rev命令反转文件路径,从第一个开始剪切.,然后再次反转文件路径,如下所示:
filename=`rev <<< "" | cut -d"." -f2- | rev`
fileext=`rev <<< "" | cut -d"." -f1 | rev`
回答by vincent gravitas
If you want to play nice with Windows file paths (under Cygwin) you can also try this:
如果你想很好地使用 Windows 文件路径(在 Cygwin 下),你也可以试试这个:
fname=${fullfile##*[/|\]}
This will account for backslash separators when using BaSH on Windows.
在 Windows 上使用 BaSH 时,这将考虑反斜杠分隔符。
回答by kom lim
A combination of basename and cut works fine, even in case of double ending like .tar.gz:
basename 和 cut 的组合效果很好,即使在双结尾的情况下也是如此.tar.gz:
fbname=$(basename "$fullfile" | cut -d. -f1)
Would be interesting if this solution needs less arithmetic power than Bash Parameter Expansion.
如果此解决方案需要比 Bash Parameter Expansion 更少的算术能力,那将会很有趣。
回答by Diomoid
Just an alternative that I came up with to extract an extension, using the posts in this thread with my own small knowledge base that was more familiar to me.
只是我想出的一种替代方法来提取扩展名,使用此线程中的帖子以及我自己更熟悉的小型知识库。
ext="$(rev <<< "$(cut -f "1" -d "." <<< "$(rev <<< "file.docx")")")"
Note: Please advise on my use of quotes; it worked for me but I might be missing something on their proper use (I probably use too many).
注意:请告知我对报价的使用;它对我有用,但我可能在正确使用时遗漏了一些东西(我可能使用了太多)。
回答by sancho.s ReinstateMonicaCellio
Here are oneliners:
这里是单线:
$(basename "${s%.*}")$(basename "${s}" ".${s##*.}")
$(basename "${s%.*}")$(basename "${s}" ".${s##*.}")
I needed this, the same as asked by bongbang and w4etwetewtwet.
我需要这个,就像 bongbang 和 w4etwetewtwet 所问的那样。
回答by agc
Pure bash, no basename, no variable juggling. Set a string and echo:
纯粹的bash,不basename,没有可变的杂耍。设置一个字符串和echo:
p=/the/path/foo.txt
echo "${p//+(*\/|.*)}"
Output:
输出:
foo
Note: the bashextgloboption must be "on", (Ubuntusets extglob"on" by default), if it's not, do:
注意:bashextglob选项必须为“on”,(Ubuntu默认将extglob设置为“on”),如果不是,请执行以下操作:
shopt -s extglob
Walking through the ${p//+(*\/|.*)}:
走过${p//+(*\/|.*)}:
${p-- start with $p.//substitute every instance of the pattern that follows.+(match one or moreof the pattern listin parenthesis, (i.e.until item #7 below).- 1stpattern:
*\/matches anything before a literal "/" char. - pattern separator
|which in this instance acts like a logical OR. - 2ndpattern:
.*matches anything after a literal "." -- that is, inbashthe "." is just a period char, and nota regex dot. )end pattern list.}end parameter expansion. With a string substitution, there's usually another/there, followed by a replacement string. But since there's no/there, the matched patterns are substituted with nothing; this deletes the matches.
${p-- 以$p开头。//替换后面的模式的每个实例。+(匹配一个或多个所述的模式列表中括号(即,直到下面项#7)。- 第一种模式:
*\/匹配文字“/”字符之前的任何内容。 - 模式分隔符
|在这种情况下就像一个逻辑 OR。 - 第二种模式:
.*匹配文字 "."之后的任何内容——也就是说,在bash"." 中只是一个句点字符,而不是正则表达式 dot。 )结束模式列表。}结束参数扩展。对于字符串替换,通常会有另一个/替换字符串,然后是替换字符串。但是因为那里没有/,匹配的模式被替换为空;这将删除匹配项。
Relevant man bashbackground:
相关man bash背景:
- pattern substitution:
- 模式替换:
${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.
${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.
- extended pattern matching:
- 扩展模式匹配:
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
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

