md5sum stellt der Prüfsumme '\' voran

22

Warum stellt md5sum "\" vor die Prüfsumme, wenn die Prüfsumme einer Datei mit "\" im Namen gefunden wird?

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

Das gleiche gilt für jedes andere Dienstprogramm.

jsaji
quelle
Nur als Referenz *sumtun die anderen Dienstprogramme (derselben Familie wie md5sumz. B. sha1sumusw.) in GNU coreutils dasselbe.
Kusalananda
Ich sehe dieses Verhalten nicht, was ist die Version des Dienstprogramms:md5sum --version
Kiwy
@Kusalananda Dies kann versionsspezifisch sein. unter CentOS 7 cksumnicht; zB% cksum test\\test 3915528286 4 test\test
Stephen Harris
@StephenHarris Das liegt wahrscheinlich daran, dass cksumes sich um ein POSIX-Dienstprogramm und dessen Spezifikation handelt. erlaubt es nicht.
Kusalananda

Antworten:

33

Dies ist für Coreutils dokumentiertmd5sum :

Wenn die Datei einen Backslash oder eine neue Zeile enthält, wird die Zeile mit einem Backslash begonnen, und jedes problematische Zeichen im Dateinamen wird mit einem Backslash maskiert, wodurch die Ausgabe auch bei Vorhandensein beliebiger Dateinamen eindeutig wird.

( Datei ist der Dateiname, nicht der Inhalt der Datei).

b2sum, sha1sumUnd die verschiedenen SHA-2 - Tools in der gleichen Art und Weise verhalten , wie md5sum. sumund cksumnicht; sumwird nur aus Gründen der Abwärtskompatibilität bereitgestellt (und seine Vorfahren erzeugen keine Ausgabe in Anführungszeichen) und cksumwird von POSIX angegeben und lässt diese Art der Ausgabe nicht zu.

Dieses Verhalten wurde im November 2015 eingeführt und in Version 8.25 (Januar 2016) mit folgendem NEWSEintrag veröffentlicht:

md5sumSorgt jetzt für eine einzelne Zeile pro Datei für den Status der Standardausgabe, indem ein '\' am Zeilenanfang verwendet und alle neuen Zeilen durch '\ n' ersetzt werden. Dies wirkt sich auch auf sha1sum, sha224sum, sha256sum, sha384sumund sha512sum.

Der Backslash am Zeilenanfang dient als Flag: Escape-Zeichen in Dateinamen werden nur verarbeitet, wenn die Zeile mit einem Backslash beginnt. (Unescaping kann nicht das Standardverhalten sein: Es würde Summen brechen, die mit älteren Versionen von Coreutils generiert wurden, die \\oder \nin den gespeicherten Dateinamen enthalten.)

Stephen Kitt
quelle
30
Es ist eine Schande, dass so etwas völlig uninteressantes auf den manSeiten nicht dokumentiert ist. (Und ja, ich bin mir bewusst, dass GNU möchte, dass infostattdessen alle ihre stark
verschlungenen
3
@msouth Der Backslash am Anfang der Zeile dient als Flag, das angibt, dass Backslashes im Dateinamen Escape-Zeichen sind. andernfalls wüsstest du nicht, ob du \nals Literale oder als Escape-Zeichen usw. arbeiten sollst .
Stephen Kitt
3
@msouth Wenn es am Anfang des Dateinamens ist, haben Sie keine Möglichkeit zu wissen, ob es das Flag ist oder ein Dateiname, der wirklich mit einem Backslash beginnt ...
Stephen Kitt
1
@StephenKitt Ich glaube nicht, dass der führende \ zur Disambiguierung da ist. Es gibt keine Mehrdeutigkeit, wenn die Ausgabe als immer ohne Backslashes und Newlines dokumentiert ist. Es ist da, damit die Entfluchtung nicht durchgeführt werden muss, wenn dies nicht erforderlich ist. Sie können natürlich darüber diskutieren, ob sich dies lohnt (persönlich denke ich, dass dies nicht der Fall ist, aber ich bin kein coreutilsMitwirkender).
TypeIA
1
Die Formulierung der Dokumentation "Jedes problematische Zeichen im Dateinamen wird mit einem Backslash maskiert" ist falsch. Das Ersetzen einer neuen Zeile durch entspricht \nnicht dem Entstehen einer neuen Zeile mit einem Backslash!
Ruakh
17

Stephen Kitts Antwort behandelt das, was und ich werde versuchen zu erklären, warum diese Änderung umgesetzt wurde. Zunächst stellte jemand fest, dass ein Dateiname mit Zeilenumbrüchen 1 zu mehrdeutigen Ausgaben führen kann . Betrachten Sie beispielsweise diese Ausgabe:

d41d8cd98f00b204e9800998ecf8427e  foo
25af89c92254a806b2e93fffd8ac1814  bar

Bedeutet dies, dass zwei Dateien vorhanden waren foound bar/ oder nur eine Datei mit dem Dateinamen "foo\n25af89c92254a806b2e93fffd8ac1814 bar"? Zugegeben, letztere Möglichkeit ist höchst unwahrscheinlich, aber möglich. Um die Mehrdeutigkeit zu beseitigen, haben sich die Entwickler dafür entschieden, Zeilenumbrüche mit einem Backslash ( \) zu umgehen . Die Ausgabe wird dann unterscheidbar. Dann gibt es jedoch eine weitere Mehrdeutigkeit:

764efa883dda1e11db47671c4a3bbd9e  foo\nbar

Enthält der Name dieser Datei einen Zeilenumbruch oder einen umgekehrten Schrägstrich, gefolgt von einem n ? Um dies zu beheben, müssen wir auch Backslashes vermeiden, damit der letztere Fall wie folgt lautet:

764efa883dda1e11db47671c4a3bbd9e  foo\\nbar

Schließlich haben sie sich dafür entschieden, jeder Ausgabezeile, die solche Escape-Zeichen enthält, ein voranzustellen \\, damit ein Parser leicht erkennen kann, ob ein Escape-Zeichen ausgeführt wurde. Vermutlich wurde dies getan, um Parsern zu ermöglichen, die Ausgabe sowohl von Escape-Versionen md5sumals auch von Nicht-Escape-Versionen (Nicht-GNU) zu verarbeiten. Die Flagge bedeutet auch, dass "kostspieliges" Nicht-Entkommen nicht durchgeführt werden muss, wenn es nicht notwendig ist. Sie können ein Beispiel für dieses Parsing in Aktion in sehenmd5sum.c sich sehen (Zeile 382 in der verknüpften Version).


1 Mit Zeilenumbruch meine ich das Zeichen, \ndas manchmal auch speziell als Zeilenvorschub oder LF bezeichnet wird ; sehen md5sum.c.

TypeIA
quelle
1
Das vernünftige Verhalten wäre natürlich , jede Datei, die eine neue Zeile enthält , vollständig zu verbannen. Lehne es einfach ab, sie zu verarbeiten.
Pipe
1
@pipe es ist wahnsinniges Verhalten. POSIX lässt solche Dateinamen zu, und die Dienstprogramme, die sich absichtlich weigern, mit legitimen Dateien zu arbeiten, sind schlecht und müssen mit Feuer getötet werden.
Ruslan
2
@ Ruslan Es geht darum, gegen POSIX zu protestieren, weil sie solche unsozialen Namen zulassen . Das Zulassen solcher Zeichen hat wahrscheinlich eine große Menge von Sicherheitsproblemen verursacht und den Code aufgebläht, nur um solche Sonderfälle zu behandeln.
Pipe
@pipe während LF in einem Dateinamen in der Tat unsozial ist, sind andere Dinge in Ihrem Link erwähnt viel mehr umstritten - wie Leerzeichen, nicht-lateinische Buchstaben usw.
Ruslan
Klassisches Über-Engineering durch Ingenieure. Lektion (noch einmal): Lassen Sie Ingenieure nicht die Anforderungen fahren. Sie werden den dunkelsten und verworrensten Fall finden und ihn zum dominierenden Fall erheben und alle verwirren.