Answers:
这是使用Bash中的#和%运算符进行操作的方法。
$ x="/foo/fizzbuzz.bar"
$ y=${x%.bar}
$ echo ${y##*/}
fizzbuzz
${x%.bar}
也可以${x%.*}
删除一个点${x%%.*}
后的所有内容或删除第一个点后的所有内容。
例:
$ x="/foo/fizzbuzz.bar.quux"
$ y=${x%.*}
$ echo $y
/foo/fizzbuzz.bar
$ y=${x%%.*}
$ echo $y
/foo/fizzbuzz
文档可以在Bash手册中找到。查找${parameter%word}
和${parameter%%word}
尾随部分匹配的部分。
看一下basename命令:
NAME="$(basename /foo/fizzbuzz.bar .bar)"
使用基本名,我使用以下方法来实现此目的:
for file in *; do
ext=${file##*.}
fname=`basename $file $ext`
# Do things with $fname
done;
这不需要文件扩展名的先验知识,即使您的文件名的文件名中带有点(在文件扩展名的前面)也可以使用。尽管确实需要该程序basename
,但这是GNU coreutils的一部分,因此它应该随发行版一起提供。
fname=`basename $file .$ext`
纯bash方式:
~$ x="/foo/bar/fizzbuzz.bar.quux.zoom";
~$ y=${x/\/*\//};
~$ echo ${y/.*/};
fizzbuzz
在man bash的“参数扩展”下解释了此功能。非bash方式比比皆是:awk,perl,sed等。
编辑:使用文件后缀中的点,并且不需要知道后缀(扩展名),但不适用于名称本身中的点。
basename和dirname函数是您所需要的:
mystring=/foo/fizzbuzz.bar
echo basename: $(basename "${mystring}")
echo basename + remove .bar: $(basename "${mystring}" .bar)
echo dirname: $(dirname "${mystring}")
输出:
basename: fizzbuzz.bar
basename + remove .bar: fizzbuzz
dirname: /foo
mystring=$1
,而不是电流恒定值(这将抑制一些警告,是一定不能包含空格/水珠字符/等),以及解决这些问题的这发现?
echo "basename: $(basename "$mystring")"
-如果这样mystring='/foo/*'
,你没有得到*
替换在当前目录中的文件列表后 basename
完成。
使用basename
假设您知道文件扩展名是不是?
而且我相信,各种正则表达式建议都不能解决一个文件名包含多个“”的问题。
以下似乎可以应付双点。哦,文件名本身也包含“ /”(仅用于踢)
用帕斯卡(Pascal)来解释:“很抱歉,这个脚本太长了。我没有时间将其缩短。”
#!/usr/bin/perl
$fullname = $ARGV[0];
($path,$name) = $fullname =~ /^(.*[^\\]\/)*(.*)$/;
($basename,$extension) = $name =~ /^(.*)(\.[^.]*)$/;
print $basename . "\n";
除了此答案中使用的符合POSIX的语法外,
basename string [suffix]
如
basename /foo/fizzbuzz.bar .bar
GNUbasename
支持另一种语法:
basename -s .bar /foo/fizzbuzz.bar
结果相同。区别和优点是-s
暗含-a
,它支持多个参数:
$ basename -s .bar /foo/fizzbuzz.bar /baz/foobar.bar
fizzbuzz
foobar
甚至可以通过使用-z
选项将输出与NUL字节分开来使文件名安全,例如对于包含空白,换行符和glob字符(用引号ls
)的以下文件:
$ ls has*
'has'$'\n''newline.bar' 'has space.bar' 'has*.bar'
读入数组:
$ readarray -d $'\0' arr < <(basename -zs .bar has*)
$ declare -p arr
declare -a arr=([0]=$'has\nnewline' [1]="has space" [2]="has*")
readarray -d
需要Bash 4.4或更高版本。对于较旧的版本,我们必须循环:
while IFS= read -r -d '' fname; do arr+=("$fname"); done < <(basename -zs .bar has*)
将排名靠前的答案与排名靠后的答案相结合,以获得不带完整路径的文件名:
$ x="/foo/fizzbuzz.bar.quux"
$ y=(`basename ${x%%.*}`)
$ echo $y
fizzbuzz
${parameter%word}
以及${parameter%%word}
在尾部匹配部分中找到。