linux一行命令批量修改文件名中的部分字符(包含子目录下的文件)

逆流の鱼, 29 五月, 2013
起因是为tinymce安装汉化包,安装后效果如下: 通过find命令查找: find ./ -name zh-cn*
./themes/simple/langs/zh-cn.js
./themes/advanced/langs/zh-cn_dlg.js
./themes/advanced/langs/zh-cn.js
./plugins/media/langs/zh-cn_dlg.js
./plugins/style/langs/zh-cn_dlg.js
./plugins/emotions/langs/zh-cn_dlg.js
./plugins/paste/langs/zh-cn_dlg.js
./plugins/advlink/langs/zh-cn_dlg.js
./plugins/table/langs/zh-cn_dlg.js
./plugins/fullpage/langs/zh-cn_dlg.js
./plugins/advimage/langs/zh-cn_dlg.js
./plugins/template/langs/zh-cn_dlg.js
./plugins/advhr/langs/zh-cn_dlg.js
./plugins/xhtmlxtras/langs/zh-cn_dlg.js
./plugins/searchreplace/langs/zh-cn_dlg.js
./langs/zh-cn.js
可恶的drupal不认zh-cn前缀,必须要改为zh-hans前缀。尽管可以写模块修复这个bug,但既然改名就可以了又何必装模块。 然而汉化包是会升级的,我不可能每次更新都傻乎乎地去逐个改名,因此有必要需求一个高效率的批量改名技巧。 于是在网上疯狂寻找方法,无论find+sed,还是rename/sed,都无法进入子目录后替换文件名中的字符。网上找到能解决这个问题的,只有写shell脚本循环改名的方法。 我没死心,出于对linux的shell命令有充分的信心,希望一行命令就搞掂它。 先从网上找到的最接近的命令入手:
find ./ -name zh-cn*.js|sed 's/zh-cn/zh-hans/'
得出以下效果:
./themes/simple/langs/zh-hans.js
./themes/advanced/langs/zh-hans_dlg.js
./themes/advanced/langs/zh-hans.js
./plugins/media/langs/zh-hans_dlg.js
./plugins/style/langs/zh-hans_dlg.js
./plugins/emotions/langs/zh-hans_dlg.js
./plugins/paste/langs/zh-hans_dlg.js
./plugins/advlink/langs/zh-hans_dlg.js
./plugins/table/langs/zh-hans_dlg.js
./plugins/fullpage/langs/zh-hans_dlg.js
./plugins/advimage/langs/zh-hans_dlg.js
./plugins/template/langs/zh-hans_dlg.js
./plugins/advhr/langs/zh-hans_dlg.js
./plugins/xhtmlxtras/langs/zh-hans_dlg.js
./plugins/searchreplace/langs/zh-hans_dlg.js
./langs/zh-hans.js

再查看shell正则表达式的用法,发现同php的preg类似,可能保留查找的结果,用\1,\2,\3...表示供替换后重用。 区别是括号前要加个反斜杠,'/(.*)abcde/'要写成'/\(.*\)abcde/'。 着手对命令进行改造: find ./ -name zh-cn*.js|sed 's/\(.*\)\(zh-cn\)\(.*\)/mv \1\2\3 \1zh-hans\3/' 乖,终于出来了。
mv ./themes/simple/langs/zh-cn.js ./themes/simple/langs/zh-hans.js
mv ./themes/advanced/langs/zh-cn_dlg.js ./themes/advanced/langs/zh-hans_dlg.js
mv ./themes/advanced/langs/zh-cn.js ./themes/advanced/langs/zh-hans.js
mv ./plugins/media/langs/zh-cn_dlg.js ./plugins/media/langs/zh-hans_dlg.js
mv ./plugins/style/langs/zh-cn_dlg.js ./plugins/style/langs/zh-hans_dlg.js
mv ./plugins/emotions/langs/zh-cn_dlg.js ./plugins/emotions/langs/zh-hans_dlg.js
mv ./plugins/paste/langs/zh-cn_dlg.js ./plugins/paste/langs/zh-hans_dlg.js
mv ./plugins/advlink/langs/zh-cn_dlg.js ./plugins/advlink/langs/zh-hans_dlg.js
mv ./plugins/table/langs/zh-cn_dlg.js ./plugins/table/langs/zh-hans_dlg.js
mv ./plugins/fullpage/langs/zh-cn_dlg.js ./plugins/fullpage/langs/zh-hans_dlg.js
mv ./plugins/advimage/langs/zh-cn_dlg.js ./plugins/advimage/langs/zh-hans_dlg.js
mv ./plugins/template/langs/zh-cn_dlg.js ./plugins/template/langs/zh-hans_dlg.js
mv ./plugins/advhr/langs/zh-cn_dlg.js ./plugins/advhr/langs/zh-hans_dlg.js
mv ./plugins/xhtmlxtras/langs/zh-cn_dlg.js ./plugins/xhtmlxtras/langs/zh-hans_dlg.js
mv ./plugins/searchreplace/langs/zh-cn_dlg.js ./plugins/searchreplace/langs/zh-hans_dlg.js
mv ./langs/zh-cn.js ./langs/zh-hans.js
最后在命令管道后加上sh,批量执行。
find ./ -name zh-cn*.js|sed 's/\(.*\)\(zh-cn\)\(.*\)/mv \1\2\3 \1zh-hans\3/'|sh

后记

把文件名改了以后,tinymce中文还是出不来,打开一个js看看:
tinyMCE.addI18n({"zh-cn":{common:{"more_colors........
原来每个文件里的变量定义都是zh-cn,次奥!还得修改每个文件里内容!不搞了,用模块修改drupal的语言代码算了。 又把它改回原来的:
find ./ -name zh-hans*.js|sed 's/\(.*\)\(zh-hans\)\(.*\)/mv \1\2\3 \1zh-cn\3/'|sh

评论