我需要md5sum
在Python中使用管道来计算一堆.mp3文件的校验和...是否有一个命令可以忽略程序命令行上文件名中的空格md5sum
?
例如:
import os
def index(directory):
stack = [directory]
files = []
while stack:
directory = stack.pop()
for file in os.listdir(directory):
fullname = os.path.join(directory, file)
if fullname.endswith('mp3'):
files.append(fullname)
if os.path.isdir(fullname) and not os.path.islink(fullname):
stack.append(fullname)
return files
def check(directory):
files = index(directory)
hvalues = []
for x in files:
cmd = 'md5sum' + ' ' + x
fp = os.popen(cmd)
res = fp.readline()
hvalues.append(res)
stat = fp.close() # What to do with stat?
return hvalues
命令cmd = 'md5sum' + ' ' + x
无法在包含空格或特殊字符的文件上正常工作,因为“md5sum”工具缺乏正确处理(散列)文件名中包含空格的文件的能力。
答案1
正如 @binfalse 指出的,问题不在于程序md5sum
,而在于调用它的方式。您的代码实际上在几个层面上都很糟糕:
您无需转义就组装了一个 shell 命令。在最坏的情况下,如果其中一个文件名恰好是巧妙设计的,则可能会导致执行完全意想不到的命令。那将是可怕的,除非您正在编写一次性脚本。
该
os.popen()
函数已已弃用从 Python 2.6 开始。推荐的替代品是subprocess.Popen()
。请务必传递一个列表作为args
参数,而不是连接字符串,以避免前面提到的 shell 转义问题。def check(directory): files = index(directory) hvalues = [] for f in files: cmd = ['md5sum', f] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) hvalues.append(proc.stdout.readline()) proc.stdout.close() stat = os.waitpid(proc.pid, 0) return hvalues
更好的是,使用 Python
hashlib
计算哈希值。
答案2
这并不是缺乏能力,md5tool
而是一般的命令行限制。参数之间用空格分隔。因此,如果您传递包含空格的文件名,md5sum
它将把每个标记解释为单个文件。您可以通过用引号将文件名括起来来解决这个问题。也就是说,尝试更换线路
cmd = 'md5sum' + ' ' + x
和
cmd = 'md5sum' + ' "' + x + '"'
你的命令行调用看起来像
md5sum "file name with spaces.mp3"
因此,md5sum
将计算哈希而不会抱怨。