DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

curl 下载压缩文件时提示 Binary output can mess up your terminal

curl 的 -0 是 HTTP/1.0,不会保存下载文件。出现二进制输出警告时,用 --output 指定文件名,区分 -O 与 --compressed,并核对退出状态和下载完整性。

下载 .gz、图片或其他二进制文件时,curl 显示 Warning: Binary output can mess up your terminal,预期的文件却没有出现在目录里。先查看命令有没有指定输出文件,尤其要分清数字零 -0、大写字母 -O 和小写字母 -o。

例如,下面的命令并没有要求保存文件。域名和路径是示例,不能直接作为真实下载地址:

curl -0 'https://downloads.example.com/data.json.gz'

-0 的含义是使用 HTTP/1.0。curl 默认将响应正文输出到标准输出;当它发现即将向终端输出二进制数据时,可能中止写出并给出这条警告。改成 HTTP/1.0 不会决定下载文件名,也不会解压文件。

以下命令以 Linux、macOS 的普通 shell 为例,调用的是 curl 程序本身。若从笔记本单元格执行,区分单元格调用外部命令的语法与 curl 参数;换到普通终端时不要照搬开头的 !。不同终端和重定向方式会影响警告是否出现,因此“没有警告”也不等于已经保存文件。

明确给出本地文件名

要把响应保存到文件,用小写 -o 或长选项 --output:

curl --fail --show-error \
  --output './data-download.part' \
  'https://downloads.example.com/data.json.gz'

把 URL 替换为确认可信的真实下载地址。在自己有写权限的下载目录执行,并选择一个尚不存在的目标文件名;普通输出选项可能覆盖同名文件。这里用 .part 表示“尚待验收的下载结果”,curl 不会因为这个后缀而自动断点续传或进行完整性验证。

--fail 用于让 HTTP 400 及以上响应通常作为失败处理,避免把常见的错误页面当成目标文件;它不能识别所有认证失败情形,也不能判断一个 HTTP 200 响应是否就是正确文件。--show-error 在启用静默模式时保留失败信息,本条命令没有静默模式时也可以使用。

若下载地址确实通过重定向指向文件,再加 --location。它会继续请求重定向目标,因此应确认这个行为符合下载站点的预期。示例可写为:

curl --fail --show-error --location \
  --output './data-download.part' \
  'https://downloads.example.com/data.json.gz'

这些命令没有强制 HTTP/1.0。只有服务器或诊断场景明确要求该协议时,才另行保留 --http1.0;它与保存到文件是两项独立设置。

大写 O 使用 URL 中的文件名

如果确定要使用 URL 末尾的文件名,可以选大写字母 -O:

curl --fail --show-error \
  --remote-name \
  'https://downloads.example.com/data.json.gz'

--remote-name 与 -O 等价,长选项能避免把字母 O 看成数字 0。这个例子会在当前目录保存为 data.json.gz。文件名来自 URL,而不是自动采用服务器响应头里建议的名字;同名文件已存在时也可能被覆盖。URL 带有编码字符或没有明确文件名时,优先使用 --output 自己命名,避免依赖不同版本的命名细节。

小写 -o 后面必须带本地文件名,大写 -O 则不需要这个参数。它们都是输出选项,数字 -0 是协议选项,三者不能互换。

不要把强制输出或传输解压当成保存文件

警告中出现的 --output - 表示把输出目的地设为标准输出,并允许二进制数据继续写出。它不会创建一个叫作 - 的普通文件。目标是下载到磁盘时,应给出真实文件名;为了让警告消失而直接把二进制内容刷到终端,仍可能破坏终端显示。

--compressed 也不是“所有压缩包都自动解压”的开关。它请求 HTTP 压缩响应,并对支持的响应内容编码做解码。一个 URL 以 .gz 结尾,并不能证明服务器使用了这种 HTTP 内容编码:文件本身可以就是需要保存的 gzip 数据。

因此,保存原始压缩文件时先使用输出文件选项。只有目标是读取经 HTTP 内容编码压缩的响应,且确认服务器采用相应编码时,才考虑 --compressed。它可能改变保存的响应正文;不能一边启用自动解码,一边未经检查就断言输出仍是原来的压缩包。传输层解码完成,也不保证内容是可直接在终端显示的文本。

下载结束后核对状态和文件内容

在普通 shell 中,紧接下载命令读取退出状态:

printf 'curl exit status: %s\n' "$?"

这条命令应紧接 curl 执行,中间不要先运行别的命令,否则看到的就是别的命令的状态。非零表示失败,目录里即使留有文件,也不能当成完整结果。网络中断、磁盘写入失败或 HTTP 错误应按各自的具体错误处理,不要把所有写入错误都归到二进制警告上。

要在下载时同时记录最终 HTTP 状态,可以使用:

curl --fail --show-error --location \
  --output './data-download.part' \
  --write-out 'HTTP %{response_code}\n' \
  'https://downloads.example.com/data.json.gz'

--write-out 默认把这段状态文本写到标准输出,响应正文仍保存在指定文件中。即使退出状态为 0,最终状态码符合预期,还应核对文件是否为预期格式,并使用发布方提供的可信校验值或该格式的校验工具检查完整性;HTML 登录页也可能以 HTTP 200 返回。确认通过后,再把 .part 文件改为需要的正式名称。

本问题通常只需调整下载命令,不需要修改服务端、关闭 TLS 校验或改变系统权限。失败结果先保留为单独文件用于判断,重新下载时选用新的文件名;确认无用后再清理。若已覆盖原文件,撤回命令参数不会恢复原内容,只能从已有备份或可信来源恢复。