为什么(以及如何)在二进制文件上使用 cat 会弄乱终端?

为什么(以及如何)在二进制文件上使用 cat 会弄乱终端?

如果我cat正确理解手册:

连接文件并在标准输出上打印

cat将以文件作为参数并将它们打印在标准输出上。
我不明白的是,如果我使用以下命令:

cat img.png > copy.png

我将获得 2 个相同的 png 文件,而如果我只是

cat img.png  

我的终端很可能会变得混乱并误解我输入的内容。

  • 这怎么可能?
  • 二进制值仍然是二进制数据。为什么它不简单地显示一系列 0 和 1 或这些二进制数据的 ASCII 解释或无论终端中的编码是什么?
  • cat通过ing 包含奇怪字符的文本文件 也可能出现这种行为吗?
  • 是否应该实施一种机制来防止这种行为,例如 try{}catch{} 语句?

答案1

cat连接命令行上作为参数给出的文件并将连接的输出打印到标准输出。它读取字节(从概念上讲,一次一个),并且默认情况下,不对它读取的字节执行任何解释。

在第一个示例中,您将 stdout 重定向到一个文件,这就是您获得一个新文件的原因。

在第二个示例中,字节被写入终端,并且它是终点站即将字符序列解释为终端的控制序列。这就是您的终端上出现异常行为的原因。与以下无关cat 本身。  cat不知道你将如何处理它的输出。您可能会通过管道将其发送到另一个程序来解释/处理/打印它,或者将其传递给音频驱动程序以播放“雨中曲”。

因此,遵循 Unix 哲学:

做一件事,只做一件事,但要做好

cat不应试图事后猜测或解释您正在尝试做的事情。


@Kiwy 的评论如下(针对语法已修复):

这是否意味着如果您的cat二进制文件包含诸如 之类的纯文本指令rm -rf,则可以解释它?

是和不是。让我解释:

否:如果您cat使用终端,因为它(终端软件)正在将输出发送到您的屏幕,或解释控制序列(它正在模拟旧硬件,例如,电传打字机)。

:

是的:如果您cat使用管道并且接收的程序可以将字符解释为命令。

看看这个例子:

cat anyOldShellScript | bash

在此示例中,bash会将其获取的内容解释为命令,因此rm -rf如果字符存在于通过 传递到管道的内容中,则运行这些字符cat

答案2

我猜发生这种情况主要是因为代码低于 0x20 的不可打印字符。这些是特殊的控制/转义代码,用于 Backspace、Delete 等键。

相关内容