Fazendo o md5sum entender nomes de arquivos com espaços

0

Eu preciso usar md5sum em Python usando pipe para calcular a soma de verificação de um monte de arquivos .mp3 ... existe um comando que ignora espaços em branco em nomes de arquivos na linha de comando de md5sum program?

Por exemplo:

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

O comando cmd = 'md5sum' + ' ' + x não funcionará como deveria em arquivos que incluam espaços em branco ou caracteres especiais, porque a ferramenta 'md5sum' não tem a capacidade de manipular corretamente os arquivos (hashing) com espaços em branco em nomes de arquivos.

    
por Reloader 21.10.2013 / 10:15

2 respostas

1

Isso não é uma falta de habilidades no md5tool , mas uma restrição geral de linha de comando. Argumentos são separados por espaços. Portanto, se você passar um nome de arquivo contendo espaços para md5sum , ele interpretará cada token como um único arquivo. Você pode contornar isso cercando o nome do arquivo com aspas. Dito isso, tente substituir a linha

cmd = 'md5sum' + ' ' + x

com

cmd = 'md5sum' + ' "' + x + '"'

e sua chamada na linha de comando será parecida com

md5sum "file name with spaces.mp3"

Assim, md5sum calculará o hash sem reclamar.

    
por 21.10.2013 / 12:24
3

Como o @binfalse aponta, o problema não está no programa md5sum , mas na maneira como você o invocou. Seu código é ruim em vários níveis:

  1. Você montou um comando shell sem escapar. Na pior das hipóteses, isso pode levar à execução de um comando completamente não intencional se um dos nomes de arquivo for habilmente criado. Isso seria horrível, a menos que você esteja escrevendo um script descartável de uso único.

  2. A função os.popen() foi reprovada desde o Python 2.6. A substituição recomendada é subprocess.Popen() . Certifique-se de passar uma lista como o parâmetro args , não uma string concatenada, para evitar o problema de escape de shell mencionado anteriormente.

    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
    
  3. Melhor ainda, use o hashlib do Python para calcular os hashes.

por 21.10.2013 / 13:04