如何使用 curl 从 Linux 命令行下载文件

Linux 的 curl 命令不仅仅用于下载文件。本文将深入探讨 curl 的各种功能,并讨论何时应该选择使用 curl 而不是 wget。

curl 与 wget:它们之间的区别是什么?

人们常常难以区分 wget 和 curl 命令各自的优势。虽然这两个命令确实有一些功能上的重叠,例如它们都可以从远程服务器检索文件,但相似之处也就仅限于此。

wget 主要是一个 强大的下载工具,擅长下载文件、网页和整个目录。它具备智能的遍历网页链接功能,可以在整个网站上递归地下载内容,因此是一个出色的命令行下载管理器。

curl 则侧重于 满足不同的需求。尽管 curl 也能够检索文件,但它不像 wget 那样具备递归浏览网站并查找下载内容的能力。curl 的核心功能是允许你通过向远程系统发送请求,并接收和展示它们对你的响应来与远程系统进行交互。这些响应可能包含网页内容、文件,以及通过 Web 服务或 API 根据 curl 请求返回的数据。

而且,curl 的应用范围不仅限于网站。它支持超过 20 种协议,包括 HTTP、HTTPS、SCP、SFTP 和 FTP。此外,由于 curl 对 Linux 管道的出色支持,它更容易与其他命令和脚本集成。

curl 的作者在其个人网页上详细 描述了他所看到的 curl 和 wget 之间的差异

安装 curl

在我们用于撰写本文的计算机中,Fedora 31 和 Manjaro 18.1.0 已经预装了 curl。而 Ubuntu 18.04 LTS 则需要手动安装。在 Ubuntu 上,可以使用以下命令进行安装:

sudo apt-get install curl

查看 curl 版本

通过使用 --version 选项,curl 可以显示其版本号以及它支持的所有协议。

curl --version

检索网页

如果我们将 curl 指向一个网页,它会检索该网页的内容。

curl https://www.bbc.com

默认情况下,curl 会将网页的源代码直接输出到终端窗口。

请注意:如果未明确告知 curl 将内容保存为文件,它将始终将其输出到终端窗口。如果检索的文件是二进制文件,结果可能会不可预测,因为 shell 可能会尝试将二进制文件中的某些字节值解释为控制字符或转义序列。

将数据保存到文件

让我们指示 curl 将输出重定向到一个文件中:

curl https://www.bbc.com > bbc.html

这次我们没有看到检索到的信息,它被直接发送到了文件中。由于没有终端窗口输出,curl 会输出一组进度信息。

在之前的示例中没有这样做,是因为进度信息会分散在整个网页源代码中,所以 curl 会自动抑制它。

在这个例子中,curl 检测到输出被重定向到一个文件,所以可以安全地生成进度信息。

提供的信息包括:

  • % Total:要检索的总大小。
  • % Received:到目前为止检索到的数据的百分比和实际值。
  • % Xferd:如果正在上传数据,则发送的百分比和实际值。
  • 平均下载速度:平均下载速度。
  • 平均上传速度:平均上传速度。
  • 总时间:估计的传输总持续时间。
  • 花费的时间:到目前为止此传输已用的时间。
  • 剩余时间:完成传输的预计剩余时间。
  • 当前速度:此传输的当前传输速度。

由于我们将 curl 的输出重定向到了一个文件,现在我们得到一个名为 “bbc.html” 的文件。

双击该文件将打开你的默认浏览器,并显示检索到的网页。

请注意,浏览器地址栏中的地址是本地文件路径,而不是远程网站地址。

我们不必重定向输出就可以创建文件。可以使用 -o(输出)选项创建文件,并告知 curl 文件名。在这里,我们使用 -o 选项,并指定要创建的文件名为 “bbc.html”。

curl -o bbc.html https://www.bbc.com

使用进度条监控下载

要将基于文本的下载信息替换为简单的进度条,请使用 -#(进度条)选项。

curl -# -o bbc.html https://www.bbc.com

重新启动中断的下载

重新启动已终止或中断的下载非常简单。让我们开始下载一个比较大的文件。我们将使用 Ubuntu 18.04 的最新长期支持版本。我们使用 --output 选项指定要保存的文件名:“ubuntu180403.iso”。

curl --output ubuntu18043.iso http://releases.ubuntu.com/18.04.3/ubuntu-18.04.3-desktop-amd64.iso

下载开始并逐步完成。

如果我们使用 Ctrl+C 强行中断下载,会返回到命令提示符,下载也会被终止。

要重新开始下载,请使用 -C(继续)选项。这将使 curl 从目标文件中的指定点或偏移量重新开始下载。如果使用连字符 - 作为偏移量,curl 会检查文件的已下载部分并确定正确的偏移量。

curl -C - --output ubuntu18043.iso http://releases.ubuntu.com/18.04.3/ubuntu-18.04.3-desktop-amd64.iso

下载重新开始。curl 会报告它重新启动的偏移量。

检索 HTTP 标头

使用 -I(head)选项,你只能检索 HTTP 标头。这相当于发送一个 HTTP HEAD 命令 到网络服务器。

curl -I www.twitter.com

这个命令只检索信息,不下载任何网页或文件。

下载多个 URL

我们可以使用 xargs 一次下载多个 URL。 例如,我们可能想要下载构成文章或教程的一系列网页。

将这些 URL 复制到编辑器并保存到名为 “urls-to-download.txt” 的文件中。可以使用 xargs 来处理文本文件中的每一行内容作为参数,依次提供给 curl。

https://tutorials.ubuntu.com/tutorial/tutorial-create-a-usb-stick-on-ubuntu#0
https://tutorials.ubuntu.com/tutorial/tutorial-create-a-usb-stick-on-ubuntu#1
https://tutorials.ubuntu.com/tutorial/tutorial-create-a-usb-stick-on-ubuntu#2
https://tutorials.ubuntu.com/tutorial/tutorial-create-a-usb-stick-on-ubuntu#3
https://tutorials.ubuntu.com/tutorial/tutorial-create-a-usb-stick-on-ubuntu#4
https://tutorials.ubuntu.com/tutorial/tutorial-create-a-usb-stick-on-ubuntu#5

以下是我们需要使用的命令,让 xargs 一次将这些 URL 传递给 curl:

xargs -n 1 curl -O 

请注意,此命令使用了 -O(远程文件)输出命令,它使用大写的 “O”。此选项会使 curl 使用远程服务器上的文件名保存检索到的文件。

-n 1 选项告诉 xargs 将文本文件的每一行视为一个单独的参数。

当你运行命令时,你会看到多个下载开始并完成,一个接一个。

检查文件浏览器,会发现多个文件已被下载。每个文件的名称都与远程服务器上的文件名相同。

从 FTP 服务器下载文件

将 curl 与 文件传输协议 (FTP) 服务器一起使用非常简单,即使你需要使用用户名和密码进行身份验证。要使用 curl 传递用户名和密码,请使用 -u(用户)选项,输入用户名、一个冒号 “:” 和密码。不要在冒号前后添加空格。

这是一个由 Rebex 托管的免费测试 FTP 服务器。测试 FTP 站点预设的用户名是 “demo”,密码是 “password”。请勿在生产环境或“真实”FTP 服务器上使用这种弱用户名和密码。

curl -u demo:password ftp://test.rebex.net

curl 检测到我们将其指向 FTP 服务器,并返回服务器上存在的文件列表。

此服务器上唯一的文件是 “readme.txt” 文件,长度为 403 字节。让我们获取它。使用与之前相同的命令,并添加文件名:

curl -u demo:password ftp://test.rebex.net/readme.txt

文件被检索,curl 在终端窗口中显示其内容。

在大多数情况下,将检索到的文件保存到磁盘会更方便,而不是在终端窗口中显示。我们可以再次使用 -O(远程文件)输出命令将文件保存到磁盘,文件名与远程服务器上的文件名相同。

curl -O -u demo:password ftp://test.rebex.net/readme.txt

文件被检索并保存到磁盘。我们可以使用 ls 来检查文件的详细信息。它与 FTP 服务器上的文件同名,长度相同,均为 403 字节。

ls -hl readme.txt

向远程服务器发送参数

一些远程服务器会接受发送给它们的请求中的参数。例如,这些参数可以用于格式化返回的数据,或者选择用户想要检索的具体数据。通常可以通过 curl 与 应用程序编程接口 (API) 进行交互。

举个简单的例子,ipify 网站有一个 API,可以查询以确定你的外部 IP 地址。

curl https://api.ipify.org

通过在命令中添加格式参数,并使用 “json” 作为值,我们可以再次请求我们的外部 IP 地址,但这一次返回的数据会被编码成 JSON 格式

curl https://api.ipify.org?format=json

这是另一个使用 Google API 的示例。它返回描述一本书的 JSON 对象。你必须提供的参数是书的 国际标准书号 (ISBN)。你可以在大多数书的封底找到这个号码,通常在条形码下方。这里使用的参数是 “0131103628”。

curl https://www.googleapis.com/books/v1/volumes?q=isbn:0131103628

返回的数据内容非常全面:

何时选择 curl,何时选择 wget

如果我想要从网站下载内容,并且让网站的树结构递归搜索,我会使用 wget。

如果我想要与远程服务器或 API 进行交互,并且可能下载一些文件或网页,我会使用 curl,特别是当使用的协议是 wget 不支持的众多协议之一时。