有人可以建议如何重命名文件名:
head.body.date.txt
到:
head_body_date.txt
是否有单行语句来进行重命名Unix?
答案1
迭代文件名,并使用参数扩展进行转换:
for f in *.*.*.txt; do i="${f%.txt}"; echo mv -i -- "$f" "${i//./_}.txt"; done
参数扩展模式,将文件名中的${f//./_}
所有.
s 替换为s ( )。_
$f
上面将进行一次空运行,为了进行实际的重命名,请删除echo
:
for f in *.*.*.txt; do i="${f%.txt}"; mv -i -- "$f" "${i//./_}.txt"; done
如果您想处理任何扩展,而不仅仅是.txt
:
for f in *.*.*.*; do pre="${f%.*}"; suf="${f##*.}"; \
echo mv -i -- "$f" "${pre//./_}.${suf}"; done
检查删除后的echo
实际操作:
for f in *.*.*.*; do pre="${f%.*}"; suf="${f##*.}"; \
mv -i -- "$f" "${pre//./_}.${suf}"; done
通用,对于任意数量的点,至少有一个:
for f in *.*; do pre="${f%.*}"; suf="${f##*.}"; \
mv -i -- "$f" "${pre//./_}.${suf}"; done
答案2
与perl
基于rename
$ rename -n 's/\.[^.]+$(*SKIP)(*F)|\./_/g' head.body.date.txt
rename(head.body.date.txt, head_body_date.txt)
\.[^.]+$(*SKIP)(*F)
跳过此模式并寻找替代匹配|\./_/g
全部替换.
为_
或者,使用负前瞻
$ rename -n 's/\.(?![^.]+$)/_/g' head.body.date.txt
rename(head.body.date.txt, head_body_date.txt)
确定后,删除该-n
选项
答案3
rename 's/\.(?=[^.]*\.)/_/g' *.txt
使用正则表达式替换查找.
文件名中除最后一个实例之外的所有实例(非捕获先行)并将它们替换为_
.*.*
如果您愿意的话,可以概括。
(这个特定版本rename
似乎是通过安装的util-linux
)。我正在使用Ubuntu 12.04
(是的,严重过时的机器)。
答案4
使用mv
在一行中,sed
和:rev
mv "head.body.date.txt" "$(echo head.body.date.txt | rev | sed 's/\./_/2g' | rev)"
如果你想将它应用到所有txt
当前代表中的所有文件上,使用 glob 似乎很棘手,因为它的mv
工作原理,但你可以for
在一行中执行一个循环:
for file in *.txt; do mv "$file" "$(echo $file | rev | sed 's/\./_/2g' | rev)"; done
稍长一些,但您可以在循环中匹配多个模式!