GNUmd5sum
指令有兩種模式:二進位模式和文字模式。我想差別僅在於如何處理換行符?我對嗎?
在 GNU/Linux 上,兩種模式總是產生相同的結果,因此-b
和選項的唯一用途是指示檔案名稱之前使用的-t
標誌(*
或)?
在什麼情況下這些模式會產生不同的結果?在 Windows/MacOS 系統上? (這些平台的版本可用嗎?)
答案1
在 GNU/Linux 上,兩種模式總是產生相同的結果
是的,明確地。從man md5sum
:
筆記:[原文如此] GNU 系統上的二進位和文字模式選項沒有差別。
這是來自md5sum
GNU coreutils 8.21 附帶的實作;我注意到舊版本(8.12)沒有此通知,但我認為無論如何也是如此。
儘管 AFAICTmd5sum
尚未正式標準化(例如,透過 POSIX),但它可以在各種平台上以各種實現方式使用,並且顯然需要付出一些努力來使這些平台彼此兼容,以便於跨系統使用。
與此相關,ISO/ANSI C 標準包括用於存取文件的高級流函數。作為標準的一部分,這些可在任何透過共用程式庫或編譯器實現 ISO C 的作業系統上使用。由於幾乎所有作業系統都可以使用此功能(而且它們本身通常是用 C 語言編寫的),因此它是一種通用語言,用於實現潛在的非常可移植的軟體。
md5sum
考慮到它的作用,編寫一個可以在任何作業系統上編譯和運行的程式是完全可行的。我並不是說 GNU coreutils 版本也是如此,但前面提到的高級文件流函數之一是fopen()
ISO C 強制要求包含一個b
用於打開文件的開關,以指示它正在「作為二進製文件打開」文件」。這可能意味著什麼或對系統有何要求不是標準規定,它只需要存在,以便可以在可能存在某些(任何) 的原因。
在 linux/POSIX/*nix 風格的作業系統上沒有這樣的原因,因此該開關不執行任何操作。來自 POSIX 規範(ISO C 的超集)fopen():
字元「b」無效,但為了符合 ISO C 標準,允許使用。
因此,完全可移植的md5sum
實作可能會使用 ISO 進階檔案流函數,因為沒有其他方法可以存取 ISO C 中的檔案(大多數平台,包括 POSIX 相容平台,也有自己的較低層級方法,但使用這些方法會不可移植,因為它們不在ISO C 中),而且它還應該實現-b
和標誌,以在讀取文件時-t
添加或不添加b
選項。fopen()
在毫無意義的系統上,它不會產生任何影響。
再說一遍,我並不是說 GNU 的 md5sum 是以一種完全可移植的方式編寫的,或者是從這種方式派生的,但顯然它在可操作性方面試圖遵守這種方式。請注意,擁有一個不執行任何操作的標誌與沒有該標誌不同——在前一種情況下,它被指定為可以但不執行任何操作,而在後一種情況下,使用它可能會出現錯誤或導致未定義的行為。
答案2
正如其他人已經指出的,在 GNU 系統和現代 Windows 上,這些選項沒有任何效果。
查看原始程式碼,當md5sum
與文件一起使用時,文字/二進位選項會確定在將或mode
中使用的參數。在所有符合 POSIX 的系統上,都會被忽略且沒有任何作用。fopen(const char *pathname, const char *mode)
"r"
"rb"
b
當md5sum
讀取標準輸入時coreutils
將預設為文字模式當且僅當以下所有條件均為真時:
- 定義了編譯時宏
O_BINARY
(即文字模式和二進位模式之間存在差異), - 輸入來自終端
- 且該模式不會被命令列選項覆蓋。
否則,假定二進位模式(除非被命令列選項覆蓋),並且如果O_BINARY
定義了,xset_binary_mode()
則為標準輸入呼叫。
xset_binary_mode()
是xbinary-io.h
中定義的包裝器gnulib
。如果O_BINARY
未定義,它將是一個虛擬函數,任何好的 C 編譯器都會對其進行最佳化 - 因此,即使由於某種原因調用該函數,文字與二進位最終也不會產生任何效果。
但是當O_BINARY
被定義時,xset_binary_mode()
將是 的包裝器set_binary_mode()
,在中聲明binary-io.h
的gnulib
。從這裡,我們將找到有關「二進位模式」實際上產生影響的程式設計環境的第一個線索:
#if O_BINARY
# if defined __EMX__ || defined __DJGPP__ || defined __CYGWIN__
# include <io.h> /* declares setmode() */
# define __gl_setmode setmode
# else
# define __gl_setmode _setmode
# undef fileno
# define fileno _fileno
# endif
#else
/* On reasonable systems, binary I/O is the only choice. */
/* Use a function rather than a macro, to avoid gcc warnings
"warning: statement with no effect". */
BINARY_IO_INLINE int
__gl_setmode (int fd _GL_UNUSED, int mode _GL_UNUSED)
{
return O_BINARY;
}
#endif
顯然, __EMX__
是艾伯哈德·馬特斯 eXtender,用於 MS-DOS 和 OS/2 的 32 位元模式程式設計環境。同樣,__DJGPP__
指的是用於 MS-DOS 的 DJGPP 32 位元開發系統。然後還有西格溫。所有這些程式設計環境都setmode()
依賴<io.h>
.
對於定義 的其他程式設計環境O_BINARY
,_setmode()
將使用(由對應的程式設計環境定義)。
OpenVMS 是文字模式與二進位模式比較重要的作業系統範例之一。它還知道將文字儲存為簡單字元流的 Unix 風格方式。在 OpenVMS 世界中,這顯然被稱為格式Stream_LF
- 事實上它有一個特定的名稱應該暗示它是不是格式化文字檔案的唯一可能方法。
對於好奇的人:http://neilrieck.net/docs/openvms_notes_text_files.html
總而言之,在 OpenVMS 中,non-stream simple text
檔案格式包含零個或多個記錄(行),其最大大小在檔案元資料中定義(最多可達 32767 位元組)。每行都有一個 16 位元值作為前綴,指示每行中的位元組數。不存在“行結束符”這樣的東西:當讀取了指定數量的位元組時,行結束。如果一行上的位元組數是奇數,則0x00
添加一個填充位元組以使下一行的開頭位於字對齊位址處。該填充位元組從不計入行長度。
GNU Coreutils 確實是移植到 OpenVMS。
答案3
作為補充,我想添加一些信息,即 Windows 上的計算或模式md5sum
也沒有差異。在 Windows 的 (GNU coreutils) 8.31上進行了測試。--text
--binary
md5sum
c:\temp\file-fingerprint-test\work-copy1\file-fingerprint-eol (master -> origin)
2021-05-30 - 7:35:52 PM
λ xxd unix-eol.txt
00000000: 7468 6973 2066 696c 6520 6861 7320 756e this file has un
00000010: 6978 206c 696e 6520 656e 6469 6e67 730a ix line endings.
00000020: 7468 6973 206d 6561 6e20 6974 2068 6173 this mean it has
00000030: 206f 6e6c 7920 4c46 0a only LF.
c:\temp\file-fingerprint-test\work-copy1\file-fingerprint-eol (master -> origin)
2021-05-30 - 7:36:08 PM
λ xxd win-eol.txt
00000000: 7468 6973 2066 696c 6520 6861 7320 7769 this file has wi
00000010: 6e20 206c 696e 6520 656e 6469 6e67 730d n line endings.
00000020: 0a74 6869 7320 6d65 616e 2069 7420 6861 .this mean it ha
00000030: 7320 2020 4352 204c 460d 0a s CR LF..
c:\temp\file-fingerprint-test\work-copy1\file-fingerprint-eol (master -> origin)
2021-05-30 - 7:36:15 PM
λ md5sum.exe --text *.txt
c8a8c7bb97ab554cff96a76b2a8f89fa unix-eol.txt
03b3b1458cddff2cf1c15819b1255af3 win-eol.txt
c:\temp\file-fingerprint-test\work-copy1\file-fingerprint-eol (master -> origin)
2021-05-30 - 7:36:46 PM
λ md5sum.exe --bin *.txt
c8a8c7bb97ab554cff96a76b2a8f89fa *unix-eol.txt
03b3b1458cddff2cf1c15819b1255af3 *win-eol.txt
c:\temp\file-fingerprint-test\work-copy1\file-fingerprint-eol (master -> origin)
2021-05-30 - 7:36:57 PM
λ md5sum.exe --version
md5sum (GNU coreutils) 8.31
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Ulrich Drepper, Scott Miller, and David Madore.