鱼壳:是否可以方便地剥离延伸?

Ser*_*lla 12 fish

是否有任何方便的方法从文件名中删除任意扩展名,这是什么${i%%.*}?我会坚持我的朋友sed吗?

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)


Eva*_*enn 9

如果您知道扩展名(例如_bak,一个常见的用例),这可能更方便:

for f in (ls *_bak)
    mv $f (basename $f _bak)
end
Run Code Online (Sandbox Code Playgroud)


Cla*_*dio 9

您可以使用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 读取其输入,而不是将文件名作为命令行参数传递。

  • 您还可以使用选项“--field”(“-f”)来选择第一个字段,而不是使用“[1]”。示例:`字符串分割 --right --max 1 --field 1 。$文件名`; 另外,我认为您不需要“echo”,因为“string split”已经打印输出。 (2认同)

Jos*_*dal 5

使用string matchfish内置的功能,您可以做到

set rootname (string match -r "(.*)\.[^\.]*\$" $filename)[2]
Run Code Online (Sandbox Code Playgroud)

字符串匹配返回一个包含 2 个项目的列表。第一个是整个字符串,第二个是第一个正则表达式匹配(正则表达式中括号内的内容)。所以,我们用 [2] 抓住第二个。