)一种是convmv,有一部分中文名无法处理,可能是GBK跟UTF8有部分编码重叠。
)另一种是find+iconv,只有一行命令,乱码目录下的乱码文件处理不了,另外,重复应用会有问题,但是可以处理convmv无法处理的文件。
convmv一定要加上-r选项,没法处理一级目录,一开始没注意,还以为不能用,就找find+iconv的方法,还写了一个递归处理文件名的脚本,坏处是重复应用会造成文件乱码,所以丢弃了,另外写了一个。
1 解决方法1
convmv+iconv。使用之前确保有文件备份。
> convmv --notest -r -f gbk -t utf8 /path/to/dir/ 1>convmv-out.txt 2>convmv-err.txt
convmv挺不错的,好处是自动判断文件名编码,忽略已经处理过的文件名,坏处是有些文件名会判断出错
打开convmv-err.txt,如果有"Skipping, already UTF-8"之类的数据,删了,只留文件路径,然后执行下面的命令。
> chmod +x convert_filenames_encoding.sh
> ./convert_filenames_encoding.sh convmv-err.txt gbk utf8
这是测试,不会重命名
> ./convert_filenames_encoding.sh convmv-err.txt gbk utf8 --notest
1.1 convert_filenames_encoding.sh
Pre[-]
#!/bin/bash
##convert_filenames_encoding.sh
##read filenames from file, use iconv to convert filename encoding, then rename
notest=false
if [[ $# = 4 && "$4" = "--notest" ]]; then
notest=true
fi
echo params count is $#, notest=$notest
if [[ !(($# = 3 || $notest = true) && -f "$1") ]]; then
echo "Usage:"
echo "test: convert_filenames_encoding.sh {/path/to/filenames_list} {from_encoding} {to_encoding}"
echo "apply: convert_filenames_encoding.sh {/path/to/filenames_list} {from_encoding} {to_encoding} --notest"
echo "i.e: convert_filenames_encoding.sh /home/user1/list1 gbk utf8"
exit
else
filenames_list=$1
from_encoding=$2
to_encoding=$3
function convert_filenames_encoding {
dir=$1
# take care spaces in filename
cat "$dir" | while read file_path; do
new_file_path=`iconv -f $from_encoding -t $to_encoding <<< $file_path`
if [ "$file_path" != "$new_file_path" ]; then
if [ $notest = true ]; then
# it doesn't work if filename include '\'
mv "$file_path" "$new_file_path"
else
echo mv "$file_path" "$new_file_path"
fi
fi
done
}
convert_filenames_encoding "$filenames_list"
fi
2 解决方法2
Marguerite学姐看到这篇文章,提供了一种openSUSE专用方法(针对zip文档),解释了很多,还帮忙做了测试。有一个补丁叫做openSUSE-2013-551(Created On: Tue 25 Jun 2013 07:04:03 PM CST,Summary: librcc: fix chinese charset with unzip),安装即可。由于我用的是英文环境,跟中文环境有区别,下面总结一下。
)如果是中文环境
直接用ark跟unzip就行了,没机会看到乱码。
)如果是英文环境
))设置为中文环境
把LANG环境变量设置为zh_CN.UTF-8再执行命令,比如,"env LANG=zh_CN.UTF-8 ark test.zip"、"env LANG=zh_CN.UTF-8 unzip test.zip"。
如果无效的话,那运行"env LANG=zh_CN.UTF-8 locale"命令看看LC_ALL跟LC_CTYPE的值,如果任意一个跟系统默认的值不一样,那就是设置过,把上面命令里的LANG替换为LC_ALL或LC_CTYPE。这三个环境变量都可以改变文字相关的语言环境,优先级是LC_ALL > LC_CTYPE > LANG。
打了补丁之后就只有这一种方法了,如果不设置语言环境就解压,解压出来的中文名是乱码,而且用convmv跟iconv转换都无效。
我看过打补丁前后的unzip过程(用的是strace命令),区别是打补丁之后unzip会使用跟iconv一样的方法来转换文件名,使用的字符集是根据系统的语言环境来选择的,比如,中文环境会使用/usr/lib64/gconv/GBK.so跟/usr/lib64/gconv/BIG5.so,英文环境会使用/usr/lib64/gconv/ISO8859-1.so,这就像给iconv命令传的--from-code参数,参数传错了,转换之后的文字自然是乱码。
如果想测试没有补丁的情况,那可以删除rcc-runtime,librcc0会跟着降级,unzip然后convmv。测试完重新打补丁就行了。
该补丁更详细的信息在unzip can't detect Chinese charset due to missing rcc-runtime in librcc0 - bugzilla.novell.com,有一些技术方面的描述。
上面说的是针对12.3版本,新版本可能会不一样。
3 参考资料
* Converting filenames to UTF-8 encoding - www.novell.com* > man convmv
* > man find
* > man iconv
* Re: Change file names with find and iconv - Author: FatalError - stackoverflow.com
* Re: how to pass command-line parameter to shell script? - Author: amfoster - www.linuxquestions.org
* 30分钟搞定BASH脚本编程! - Author: chu888 - fanqiang.chinaunix.net
* Re: How to apply shell command to each line of a command output? - Author: Trey Hunner - stackoverflow.com
* Advanced Bash-Scripting Guide - Author: thegrendel.abs - tldp.org
* > man bash
* Linux中Locale及shell编码问题 - Author: nathan - www.drupal001.com
=文章版本=
20130423 - 2420130510 改为html格式
20131004 增加解决方法2
20131014 根据最近的讨论及dig增加一点内容
No comments:
Post a Comment