Python 如何防止对命令行参数进行编码?

Python 如何防止对命令行参数进行编码?,python,shell,encoding,character-encoding,command-line-arguments,Python,Shell,Encoding,Character Encoding,Command Line Arguments,(问题已解决,请查看更新) 由于编码问题,我有一些文件的文件名不正确。所以我想写一个python脚本来处理它。然而,我遇到了一个奇怪的问题 为了更好地说明这一点,我将使用一个示例:文件名显示为ªþÀï·∠ï.mp3。 但是,以下结果不同: # only one mp3 file is in this directory: $ ls *mp3 | hexdump 0000000 c2 b9 c3 be 41 cc 80 69 cc 88 41 cc 82 c2 b7 4e 0000010 cc

(问题已解决,请查看更新)

由于编码问题,我有一些文件的文件名不正确。所以我想写一个python脚本来处理它。然而,我遇到了一个奇怪的问题

为了更好地说明这一点,我将使用一个示例:文件名显示为
ªþÀï·∠ï.mp3
。 但是,以下结果不同:

# only one mp3 file is in this directory:
$ ls *mp3  | hexdump 
0000000 c2 b9 c3 be 41 cc 80 69 cc 88 41 cc 82 c2 b7 4e
0000010 cc 83 43 cc a7 2e 6d 70 33 0a                  
000001a

$ echo "¹þÀï·??Ç.mp3"  | hexdump 
0000000 c2 b9 c3 be c3 80 c3 af c3 82 c2 b7 c3 91 c3 87
0000010 2e 6d 70 33 0a                                 
0000015
基本上,第二个字符串(或字节)是我想要的,但是在我的Python脚本中,命令行参数总是给我第一个字符串。我没有办法四处走动。 我注意到这只发生在MacOSX中。因此,我怀疑这个参数是由bash/system/python编码或处理的。 以下是我的工具列表:

  • Python:2.7.2
  • 操作系统:Mac OS X 10.6.7
  • Shell:
    GNUBash,3.2.48(1)版-发行版(x86_64-apple-darwin10.0)
更新:以下代码在我的Arch Linux中运行良好,但在我的Mac OS X中存在上述问题:

#!/usr/bin/env python

import sys 
import os
for name in sys.argv[1:]:
    try:
        # This line does the magic:
        new_name = name.decode('utf8').encode('latin-1').decode('gbk')
        new_name_utf8 = new_name.encode('utf8')
        if name != new_name_utf8:
            print "%s -> %s" % (name, new_name_utf8)
            os.rename(name, new_name)
    except:
        print "Ignoring %s" % name
在shell中,运行:

$ ./the_script *mp3 # Let bash pass the file name string
您可以为字符串
运行上述代码,该字符串应正确标识为
哈里路亚.mp3
。请注意,您必须具有UTF-8语言环境和支持Unicode的正确中文字体才能正确显示,或者检查以下图像:

仅供参考:我的下载程序无法识别GBK编码的文件名,它被解释为unicode字符串,编码为UTF-8。原始文件中的非ascii字节被解释为Unicode的代码点,并使用UTF-8编码,这会导致问题


更新2:Mac和Linux之间可移植的脚本现在已上载。

类似这样的内容如何:

J=1
for I in * ; do
    mv -i "$I" "$J"
    J=$((J+1))
done

这将遍历所有文件并将它们重命名为序列号,这样您就可以消除有问题的字符。

问题是MacOS X的默认文件系统会将您提供给它的所有文件名更改为不使用预合成字符的异常规范化形式。unicodedata Python模块允许在这些表单之间进行转换,例如:

import unicodedata
print len(unicodedata.normalize("NFD", u"\u00C7"))
print len(unicodedata.normalize("NFC", u"\u00C7"))

它们分别打印2和1。

我怀疑终端/外壳本身的编码方式不同,Python无法控制它。你能举一个例子,一个Python脚本通过子进程调用调用你自己的Python脚本,并将命令行参数作为函数参数传递,而不是直接从终端进行传递。你的脚本是在目录本身中迭代,还是在传递文件名(单独传递还是作为通配符传递)命令行上的脚本?@John我在传递参数。一个观察是,我可以使用这两个字符串来打开文件。为什么特定的字节序列对您很重要?这两个转储都是UTF-8字符串,只有第二个较短的转储是预编译的(它使用重音字符的直接代码点),而第一个较长的转储有单独的组合标记。您可以发布python代码吗?您是否尝试过使用不同的shell,例如
csh
sh
?这并不能解决问题,我想检测原始文件名。请检查我的更新。正是我想要的答案!现在问题解决了!!!非常感谢!