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 的超集)打开():
字符“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.