rename是Linux下的批量文件名更改工具。怎么好用以前也只不过是听说,今天有机会试用之。
正巧有一批文件,命名方式颇为奇特,
001ac.jpg 002ae.jpg 003.ag.jpg ... 012gf.jpg
是这么一个序列,前面是正常的数字序列,加两个冒似无序的字母,其实是也是有序的。要的结果是得到正常的
001.jpg 002.jpg 003.jpg ... 012.jpg
一开始想到的可以用bash的tr来做,冒似要写复杂的脚本,用来得到文件名,然后tr掉,然后再改名。
rename的用法是, rename a b * , 意思是把文件名里的a转换成b。
那么取得a到z的循环,执行两次 rename 或许能把字母给过滤掉。于是
#!/bin/sh
for i in {a..z}
do
rename $i '' *.jpg
rename $i '' *.jpg
done
能成吗?不能。结果是执行到 g 的时候把文件名的全换成 .jp的了,于是第二次rename找不到文件名。不过rename还有第二个用法,就是改文件名。既然第一次换字母可能把文件名后缀给换掉,其实把文件名后缀先换成非字母就可以了。于是
#!/bin/sh
rename .jpg .89 *
for i in {a..z}
do
rename $i '' *.89
rename $i '' *.89
done
rename .89 .jpg *
即一开始就把后缀换成数字的,然后把字母全strip掉,然后再把数字后缀的换回正常的jpg后缀。搞定了。
后续:
好吧,apporc把问题贴到stackoverflow了,那咱也来学习一下相关的bash技巧。首先是apporc自己的方案:
1 #!/bin/bash
2
3 for i in `find . -name "*.jpg"`
4 do
5 j=${i:0:3}
6 echo $j
7 mv $i $j.jpg
8 done
看准了名字序列只有前面三个字母有效,于是取出来,重命名之。这方案很好啊,为啥他还说wired …
find . -name "*.jpg" | while read $name
do
newName=${name:0:3}
mv $i $j.jpg
done
这是David W的改写版本,获取方式不一样而已。然后看它下一个方案
for number in {1..100}
do
zf_number=$(printf "%3d", $number) #Zero fill number
if [ -e ${zf_number}* ]
then
mv ${zf_number}* $zf_number.jpg
fi
done
这是先取得数字序列,然后通过匹配数字名的方法来改名,感觉繁琐了一点。
#!/bin/bash
for i in $( find . -name “*.jpg”) ;do
new=$(echo “$i” | sed ‘s/[A-Za-z.][A-Za-z.]*//g’)
echo $new
echo mv $i $new.jpg
done
这是另一个用户shellter的方案。直接是把文件名的字母全过滤掉,然后再重命名回来。不用说,它sed的正则用得很熟。