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 basename
command. 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 rev
command 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 bash
extgloboption must be "on", (Ubuntusets extglob"on" by default), if it's not, do:
注意:bash
extglob选项必须为“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, inbash
the ".
" 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 bash
background:
相关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