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

起因是为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
文章分类: 
文章标签: