用除扩展名以外的下划线替换文件名中的点

S G*_*S G 12 command-line rename mv

有人可以建议如何重命名文件名:

head.body.date.txt
Run Code Online (Sandbox Code Playgroud)

到:

head_body_date.txt
Run Code Online (Sandbox Code Playgroud)

在Unix 中是否有单行语句来进行重命名?

hee*_*ayl 12

迭代文件名,并使用参数扩展进行转换:

for f in *.*.*.txt; do i="${f%.txt}"; echo mv -i -- "$f" "${i//./_}.txt"; done
Run Code Online (Sandbox Code Playgroud)

参数扩展模式${f//./_}将文件名 ( )中的所有.s替换为_s $f。

以上将做一个试运行,让实际重命名发生,删除echo:

for f in *.*.*.txt; do i="${f%.txt}"; mv -i -- "$f" "${i//./_}.txt"; done
Run Code Online (Sandbox Code Playgroud)

如果您想处理任何扩展,而不仅仅是.txt:

for f in *.*.*.*; do pre="${f%.*}"; suf="${f##*.}"; \
                     echo mv -i -- "$f" "${pre//./_}.${suf}"; done
Run Code Online (Sandbox Code Playgroud)

检查删除echo实际操作后:

for f in *.*.*.*; do pre="${f%.*}"; suf="${f##*.}"; \
                     mv -i -- "$f" "${pre//./_}.${suf}"; done
Run Code Online (Sandbox Code Playgroud)

通用,对于任意数量的点,至少有一个:

for f in *.*; do pre="${f%.*}"; suf="${f##*.}"; \
                 mv -i -- "$f" "${pre//./_}.${suf}"; done
Run Code Online (Sandbox Code Playgroud)


Sun*_*eep 5

与perl基于rename

$ rename -n 's/\.[^.]+$(*SKIP)(*F)|\./_/g' head.body.date.txt 
rename(head.body.date.txt, head_body_date.txt)
Run Code Online (Sandbox Code Playgroud)
  • \.[^.]+$(*SKIP)(*F) 跳过此模式并寻找替代匹配
  • |\./_/g全部替换.为_

或者,使用负前瞻

$ rename -n 's/\.(?![^.]+$)/_/g' head.body.date.txt 
rename(head.body.date.txt, head_body_date.txt)
Run Code Online (Sandbox Code Playgroud)

一旦没问题,请删除该-n选项