删除文件名中倒数第二个扩展名

elb*_*rna 5 shell sed shell-script filenames rename

例如,假设一个文件夹包含许多扩展名错误的文件

Song1.avi.mp3
Song2.avi.mp3
Song32.web.mp3
Song23.mp4.mp3
Song2a.mp9.mp3
Run Code Online (Sandbox Code Playgroud)

我只想删除第二个字段 ( web, avi, mp4)。我知道如何处理 sed 但我必须放置扩展名

 mv -v $i "$(echo $i|sed 's:.flv::g;s:.avi::g;s:.mp4::g')"
Run Code Online (Sandbox Code Playgroud)

有人知道使用 sed 或 awk 或 perl 的直接方法来仅删除第二个坏扩展吗?

Gil*_*il' 11

您不需要任何外部实用程序,您可以使用shell 自己的字符串操作功能来完成。这可以更轻松地避免破坏带有特殊字符的文件名。并记住始终在变量替换周围使用双引号

mv -v -- "$i" "${i%.*.*}.${i##*.}"
Run Code Online (Sandbox Code Playgroud)

(显然,此代码段假定文件名确实包含两个扩展名。如果不包含,则${i%.*.*}是整个文件名。)


gle*_*man 6

使用 bash 正则表达式:

f=foo.bar.baz.qux
if [[ $f =~ (.+)\.[^.]+\.([^.]+)$ ]];then
    new="${BASH_REMATCH[1]}.${BASH_REMATCH[2]}"
    if [[ -f "$new" ]]; then
        echo "moving $f would overwrite $new"
    else
        echo mv "$f" "$new"
    fi
fi
Run Code Online (Sandbox Code Playgroud)
mv foo.bar.baz.qux foo.bar.qux
Run Code Online (Sandbox Code Playgroud)

如果名称中的点数少于 2 个,则这样做的优点是什么都不做。


mik*_*erv 5

如果您需要验证文件名匹配 - 因此只重命名那些实际上具有您尝试修改的两个扩展名的文件 - 您可以这样做:

case ${i##*/} in (*.*.*)
mv -- "$i" "${i%.*.*}.${i##*.}"
;;esac
Run Code Online (Sandbox Code Playgroud)

请了解,如果您不验证匹配项并且您正在"$i"使用以下 glob 进行设置:

for i in *
mv "$i" ...
Run Code Online (Sandbox Code Playgroud)

...然后使用与上述相同的mv命令(以及其他答案)可能会导致文件被移动,"$i.$i"因为如果模式不匹配,var 会扩展到自身。