在bash中提取不带路径和扩展名的文件basename

给出如下文件名:

/the/path/foo.txt
bar.txt

我希望得到:

foo
bar

为什么这行不通?

#!/bin/bash


fullfile=$1
fname=$(basename $fullfile)
fbname=${fname%.*}
echo $fbname

正确的做法是什么?

612349 次浏览

你不必调用外部basename命令。相反,你可以使用以下命令:

$ s=/the/path/foo.txt
$ echo "${s##*/}"
foo.txt
$ s=${s##*/}
$ echo "${s%.txt}"
foo
$ echo "${s%.*}"
foo

注意,这个解决方案应该在所有最近的(2004后) POSIX兼容shell中工作,(例如bashdashksh等)。

来源:2.6.2参数展开

更多关于bash字符串操作:http://tldp.org/LDP/LG/issue18/bash.html

basename命令有两个不同的调用;在一种情况下,您只指定路径,在这种情况下,它会给出最后一个组件,而在另一种情况下,您还会给出一个后缀,它将删除该后缀。因此,您可以通过使用basename的第二次调用来简化示例代码。此外,要注意正确引用:

fbname=$(basename "$1" .txt)
echo "$fbname"

使用basename命令。它的manpage在这里:http://unixhelp.ed.ac.uk/CGI/man-cgi?basename

下面是另一种(更复杂的)获取文件名或扩展名的方法,首先使用rev命令来反转文件路径,从第一个.开始剪切,然后再次反转文件路径,如下所示:

filename=`rev <<< "$1" | cut -d"." -f2- | rev`
fileext=`rev <<< "$1" | cut -d"." -f1 | rev`

如果你想更好地使用Windows文件路径(在Cygwin下),你也可以试试这个:

fname=${fullfile##*[/|\\]}

这将在Windows上使用BaSH时考虑反斜杠分隔符。

basename和cut的组合可以很好地工作,即使是在双结尾的情况下,如.tar.gz:

fbname=$(basename "$fullfile" | cut -d. -f1)

如果这个解决方案比Bash参数扩展需要更少的算术能力,那将是有趣的。

只是一个替代方案,我提出了提取一个扩展,使用帖子在这个线程与我自己的小知识库,我更熟悉。

ext="$(rev <<< "$(cut -f "1" -d "." <<< "$(rev <<< "file.docx")")")"

注:请对我的引用提出建议;它对我有用,但我可能在正确使用上遗漏了一些东西(我可能用得太多了)。

以下是一些简单的句子:

  1. $(basename "${s%.*}")
  2. $(basename "${s}" ".${s##*.}")

我需要这个,和bongbang和w4etwetewtwet问的一样。

纯粹的bash,没有basename,没有变量杂耍。设置一个字符串和echo:

p=/the/path/foo.txt
echo "${p//+(*\/|.*)}"

输出:

foo

注意:bash extglob选项必须为“on”,(Ubuntu默认设置extglob为“on”),如果不是,请执行:

shopt -s extglob

遍历${p//+(*\/|.*)}:

  1. ${p——从$ p开始。
  2. //替换后面模式的每个实例。
  3. +(匹配括号中模式列表一个或多个 (即。直到下面第7项)。
  4. 1日模式:*\/匹配字面“/”字符之前的任何内容。
  5. 模式分隔符|,在这个例子中就像逻辑或
  6. 2日模式:.*匹配文字“.”之后的任何内容——也就是说,在bash中,“.”只是一个句点字符,而则是一个正则表达式点
  7. )结束模式列表
  8. }结束参数展开。对于字符串替换,通常会有另一个/,后面跟着一个替换字符串。但由于那里没有/,匹配的模式将被替换为任何东西;这将删除匹配项。

相关的man bash背景:

  1. 模式替换:
  ${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.
  1. 扩展模式匹配:
  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