O md5sum acrescenta '\' à soma de verificação

22

Por que o md5sum está anexando "\" na frente da soma de verificação ao localizar a soma de verificação de um arquivo com "\" no nome?

$ md5sum /tmp/test\\test
\d41d8cd98f00b204e9800998ecf8427e  /tmp/test\\test

O mesmo é observado para todos os outros utilitários.

jsaji
fonte
Apenas para referência, os outros *sumutilitários (da mesma família que md5sum, e, g, sha1sumetc.) nos coreutils do GNU fazem o mesmo.
Kusalananda
Não vejo este comportamento, o que é a versão do utilitário:md5sum --version
kiwy
@Kusalananda Pode ser uma versão específica do coreutils; no CentOS 7 cksumnão; por exemplo,% cksum test\\test 3915528286 4 test\test
Stephen Harris
@StephenHarris Isso provavelmente ocorre porque cksumé um utilitário POSIX e suas especificações. não permite isso.
Kusalananda

Respostas:

33

Isso está documentado , para o Coreutils md5sum:

Se o arquivo contiver uma barra invertida ou nova linha, a linha será iniciada com uma barra invertida e cada caractere problemático no nome do arquivo será escapado com uma barra invertida, tornando a saída inequívoca, mesmo na presença de nomes de arquivo arbitrários.

( arquivo é o nome do arquivo, não o conteúdo do arquivo).

b2sum, sha1sumE as várias ferramentas de SHA-2 se comportam da mesma forma md5sum. sume cksumnão; sumé fornecido apenas para compatibilidade com versões anteriores (e seus ancestrais não produzem saída entre aspas) e cksumé especificado pelo POSIX e não permite esse tipo de saída.

Esse comportamento foi introduzido em novembro de 2015 e lançado na versão 8.25 (janeiro de 2016), com a seguinte NEWSentrada:

md5sumagora garante uma única linha por arquivo para o status na saída padrão, usando um '\' no início da linha e substituindo qualquer nova linha por '\ n'. Isso também afeta sha1sum, sha224sum, sha256sum, sha384sume sha512sum.

A barra invertida no início da linha serve como um sinalizador: escapes nos nomes de arquivos são processados ​​apenas se a linha começar com uma barra invertida. (Desescanear não pode ser o comportamento padrão: ele quebraria as somas geradas com versões mais antigas do Coreutils que continham \\ou \nnos nomes de arquivos armazenados.)

Stephen Kitt
fonte
30
É uma pena que algo completamente pouco intuitivo como esse não esteja documentado nas manpáginas. (E sim, eu estou ciente GNU quer todos poderão ler seus altamente complicadas infopáginas em seu lugar.)
roaima
3
@msouth a barra invertida no início da linha serve como um sinalizador indicando que as barras invertidas no nome do arquivo são escapadas; caso contrário, você não saberia se processa \netc. como literais ou escapes.
Stephen Kitt
3
@msouth se é no início do nome do arquivo, você tem nenhuma maneira de saber se é a bandeira, ou um nome de arquivo realmente começando com uma barra invertida ...
Stephen Kitt
1
@StephenKitt Eu não acho que o \ principal esteja lá para a desambiguação. Não há ambiguidade se a saída estiver documentada como sempre escapando de barras invertidas e novas linhas. Está lá para que a fuga não precise ser feita se não for necessário. É claro que você pode debater se vale a pena (pessoalmente acho que não, mas não sou coreutilscolaborador).
TypeIA
1
A frase da documentação "cada caractere problemático no nome do arquivo é escapado com uma barra invertida" está incorreta; substituir uma nova linha por \nnão é o mesmo que escapar de uma nova linha com uma barra invertida!
Ruakh
17

A resposta de Stephen Kitt cobre o quê e tentarei abordar por que essa mudança foi implementada. Primeiro, alguém observou que um nome de arquivo contendo novas linhas 1 poderia resultar em uma saída ambígua . Por exemplo, considere esta saída:

d41d8cd98f00b204e9800998ecf8427e  foo
25af89c92254a806b2e93fffd8ac1814  bar

Isso significa que havia dois arquivos fooe bar, ou apenas um arquivo cujo nome de arquivo é "foo\n25af89c92254a806b2e93fffd8ac1814 bar"? É verdade que essa última possibilidade é altamente improvável, mas é possível. Para resolver a ambiguidade, os desenvolvedores optaram por escapar de novas linhas com uma barra invertida ( \). A saída então se torna distinguível. No entanto, há uma outra ambiguidade:

764efa883dda1e11db47671c4a3bbd9e  foo\nbar

O nome deste arquivo contém uma nova linha ou uma barra invertida seguida por um n? Para resolver isso, precisamos escapar de barras invertidas também, para que o último caso se torne:

764efa883dda1e11db47671c4a3bbd9e  foo\\nbar

Finalmente, eles optaram por anexar previamente cada linha de saída que contém esses escapes com a \\para facilitar a análise de um analisador se o escape foi realizado. Presumivelmente, isso foi feito para permitir que os analisadores manipulem a saída das versões de escape md5sume de versões não escapantes (não GNU). A bandeira também significa que a fuga "dispendiosa" não precisa ser feita quando não é necessária. Você pode ver um exemplo dessa análise em ação em md5sum.csi (linha 382 na versão vinculada).


1 Por nova linha, quero dizer o caractere \nque às vezes também é chamado de avanço de linha ou LF ; veja md5sum.c.

TypeIA
fonte
1
É claro que o comportamento sensato seria banir completamente todos os arquivos que contenham uma nova linha. Apenas se recuse a processá-los.
pipe
1
@pipe é um comportamento insano . O POSIX permite esses nomes de arquivos e os utilitários que se recusam a trabalhar com arquivos legítimos intencionalmente são ruins e devem ser mortos com fogo.
Ruslan
2
@Ruslan O objetivo é protestar contra o POSIX por permitir tais nomes anti-sociais . Permitir que esses caracteres provavelmente tenha causado uma grande quantidade de problemas de segurança e aumento de código apenas para lidar com casos especiais.
pipe
@pipe enquanto LF em um nome de arquivo é de fato anti-social, outras coisas mencionadas no seu link são muito mais discutíveis - como espaços, letras não-latinos etc ..
Ruslan
Excesso de engenharia clássico por engenheiros. Lição (mais uma vez): não permita que os engenheiros conduzam os requisitos. Eles encontrarão o caso mais obscuro e complicado e o elevarão ao caso dominante e confundirão a todos.