在bash中提取没有path和扩展名的文件基本名称
鉴于这样的文件名称:
/the/path/foo.txt bar.txt 我希望得到:
 foo bar 
为什么这不起作用?
 #!/bin/bash fullfile=$1 fname=$(basename $fullfile) fbname=${fname%.*} echo $fbname 
什么是正确的方法来做到这一点?
 您不必调用外部basename命令。 相反,你可以使用下面的命令: 
 $ s=/the/path/foo.txt $ echo ${s##*/} foo.txt $ s=${s##*/} $ echo ${s%.txt} foo $ echo ${s%.*} foo 
 请注意,这个解决scheme应该可以在所有最近的( 2004年以后 )兼容POSIX的 shell(例如bash , dash , ksh等)中工作。 
源: Shell命令语言2.6.2参数扩展
更多关于bash的string操作: http : //tldp.org/LDP/LG/issue18/bash.html
basename命令有两个不同的调用; 在一个,你指定的path,在这种情况下,它给你最后一个组件,而在另一个你也给一个后缀,它将被删除。 所以,你可以使用第二次调用基本名称来简化你的示例代码。 另外,要小心地正确引用的东西:
fbname = $(basename“$ 1”.txt) 回声“$ fbname”
 基本名称和剪切的组合工作正常,即使在双重结局如.tar.gz情况下: 
 fbname=$(basename "$fullfile" | cut -d. -f1) 
如果这个解决scheme比Bash参数扩展需要更less的算术能力,这将是有趣的。
 纯粹的bash ,没有basename ,没有变数的杂耍。 设置一个string和echo : 
 s=/the/path/foo.txt echo ${s//+(*\/|.*)} 
输出:
 foo 
 注意: bash extglob选项必须是“on”(在Ubuntu上默认为“on”),如果不是这样的话: 
 shopt -s extglob 
 遍历${s//+(*\/|.*)} : 
-   ${s– 从$ s开始。
-   //replace模式的每个实例。
-   +(在括号中匹配一个或多个 模式列表 。
-   *\/匹配/之前的任何内容。 (第一种模式)
-  |要么。 (模式分隔符)
-   .*匹配任何东西.。 (第二模式)
-   )结束模式列表 。
-   }结束参数扩展 – 因为没有/(将在一个string替代之前),匹配的模式被删除。
 相关的man bash背景: 
- 模式replace :
${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
 这是获取文件名或扩展名的另一种(更复杂的)方式,首先使用rev命令反转文件path,从第一个文件中删除. 然后再次反转文件path,如下所示: 
 filename=`rev <<< "$1" | cut -d"." -f2- | rev` fileext=`rev <<< "$1" | cut -d"." -f1 | rev` 
这里是线索:
-  $(basename ${s%.*})
-  $(basename ${s} .${s##*.})
我需要这个,就像bongbang和w4etwetewtwet一样。
如果你想玩Windows文件path(在Cygwin下),你也可以试试这个:
 fname=${fullfile##*[/|\\]} 
在Windows上使用BaSH时,这将占用反斜线分隔符。
只是一个替代scheme,我提出了一个扩展,使用在这个线程中的职位,我自己的小知识基础,这是我更熟悉。
 ext="$(rev <<< "$(cut -f "1" -d "." <<< "$(rev <<< "file.docx")")")" 
注意:请告诉我使用报价; 它为我工作,但我可能会错过一些正确的使用(我可能使用太多)。
使用basename命令。 其手册页是: http : //unixhelp.ed.ac.uk/CGI/man-cgi?basename