mat*_*mc3 22
--- 更新2022-08-02 ---
从 Fish 3.5+ 开始,有一个path命令 ( docs ) 旨在处理剥离扩展:
$ touch test.txt.bak
$ path change-extension '' ./test.txt.bak
test.txt
Run Code Online (Sandbox Code Playgroud)
您还可以删除一定数量的扩展:
set --local file ./test.txt.1.2.3
for i in (seq 3)
set file (path change-extension '' $file)
end
echo $file
# ./test.txt
Run Code Online (Sandbox Code Playgroud)
或者删除所有扩展:
set --local file ./test.txt.1.2.3
while path extension $file
set file (path change-extension '' $file)
end
echo $file
# ./test
Run Code Online (Sandbox Code Playgroud)
---原答案---
Fishstring命令仍然是处理此问题的规范方法。它有一些非常好的子命令,尚未在其他答案中显示。
split让您从右侧拆分最多 1 个,这样您就可以得到最后一个扩展。
for f in *
echo (string split -m1 -r '.' "$f")[1]
end
Run Code Online (Sandbox Code Playgroud)
replace允许您使用正则表达式来删除扩展名,定义为字符串末尾的最后一个点
for f in *
string replace -r '\.[^\.]*$' '' "$f"
end
Run Code Online (Sandbox Code Playgroud)
man string了解更多信息和一些很好的例子。
更新:
如果您的系统有适当的basename实用dirname程序,您可以使用如下内容:
function stripext \
--description "strip file extension"
for arg in $argv
echo (dirname $arg)/(string replace -r '\.[^\.]+$' '' (basename $arg))
end
end
Run Code Online (Sandbox Code Playgroud)
gle*_*man 10
不.fish比bash具有更小的功能集,依赖于外部命令:
$ set filename foo.bar.baz
$ set rootname (echo $filename | sed 's/\.[^.]*$//')
$ echo $rootname
foo.bar
Run Code Online (Sandbox Code Playgroud)
如果您知道扩展名(例如_bak,一个常见的用例),这可能更方便:
for f in (ls *_bak)
mv $f (basename $f _bak)
end
Run Code Online (Sandbox Code Playgroud)
您可以使用string命令从文件名中去除扩展名:
echo (string split -r -m1 . $filename)[1]
Run Code Online (Sandbox Code Playgroud)
这将filename在最右边的点处拆分并打印结果列表的第一个元素。如果没有点,该列表将包含一个带有filename.
如果您还需要去除前导目录,请将其与 basename 结合使用:
echo (basename $filename | string split -r -m1 .)[1]
Run Code Online (Sandbox Code Playgroud)
在此示例中,string从 stdin 读取其输入,而不是将文件名作为命令行参数传递。
使用string matchfish内置的功能,您可以做到
set rootname (string match -r "(.*)\.[^\.]*\$" $filename)[2]
Run Code Online (Sandbox Code Playgroud)
字符串匹配返回一个包含 2 个项目的列表。第一个是整个字符串,第二个是第一个正则表达式匹配(正则表达式中括号内的内容)。所以,我们用 [2] 抓住第二个。