我有一个 shell 脚本,用于通过 Internet 下载我的一些资料。我如何知道 Internet 上是否存在某个文件?假设我想知道它是否http://192.168.1.1/backup/01012011.zip
存在?我尝试使用ping
命令,但它显示错误,我猜这是因为/
字符。
有谁能帮助我吗?或者还有其他方法吗?
答案1
您可以使用--spider
wget 选项,它实际上并不下载文件,而只是检查文件是否存在。在您的示例中:
wget --spider http://192.168.1.1/backup/01012011.zip
200 OK
如果文件存在,则返回一条消息,或者返回一个错误,例如404 Not Found
,如果文件不存在,或者403 Forbidden
您没有权限获取它。
答案2
当然还有另一种方法 - 但这需要了解在互联网上发出请求时实际发生的情况。当您在 Web 浏览器中访问页面时,数据会使用称为 HTTP 的协议进行传输(是的,这就是您经常在 URLhttp://
开头看到的原因)。
HTTP 是一种基于文本的协议。客户端和服务器之间通过发送标头和请求正文来交换信息。标头包含大量有关请求和正在传输的信息的状态信息。您感兴趣的、可以帮助您解决问题的标头实际上根本不是标头 - 它是传输的第一行,包含一个称为状态代码的数字。此数字为 3 位数字,传达状态信息。如果请求成功,结果通常为 200(并非总是如此 - 有例外)。
有一件事是肯定的——如果你请求的文件在 Web 服务器上不存在,服务器应该回复 404 状态代码。这表示找不到资源。(对于好奇的人来说,这里是 HTTP 状态代码及其含义的列表。
好了,理论讲得够多了。让我们看看如何在终端上做到这一点。cURL 是一个使用 HTTP 获取请求的好工具,它还为我们提供了检查状态代码的能力,可在 Ubuntu 存储库中找到。您可以使用以下命令安装它:
sudo apt-get install curl
一旦安装完毕,您就可以像这样调用它:
curl [website]
...并且给定 URL 的内容将打印到终端。这是您的 Web 浏览器访问该 URL 时看到的信息。这对我们有什么帮助?好吧,仔细看看curl
命令的标志. 如果我们传递参数--head
,cURL 将返回仅有的请求中的标头。尝试使用 URL。您将获得以下形式的行列表:
header-name: header-value
当然,请注意,第一行看起来并不像这样。还记得我们之前讨论过的状态代码吗?您会在第一行中注意到它为三位数字。我们现在需要做的是使用 Perl 从第一行中提取它 - 我们可以在终端中使用 Perl 的-e
标志来执行此操作,该标志让我们将 Perl 代码直接传递给 Perl 解释器。我们还需要向 cURL ( --silent
) 添加一个额外的标志,以防止它显示进度条并弄乱我们的 Perl 脚本。
这是我们所需要的...由于需要从 shell 中转义很多内容,因此它相当复杂:
perl -e "\$s=\`curl[网址]--head --silent\`; \$s=~m/(\\d{3})/;打印 \$1"
这基本上是在用 cURL 获取 URL,然后通过 Perl 正则表达式运行它,提取状态代码并将其打印出来。
现在,您只需输入要检查的文件的 URL,并将其与“404”进行比较。如果得到“404”,则可以假设该文件不存在。
当然,这在终端上操作可能非常困难,因此您可以编写一个小脚本,使其不仅更容易理解,而且更容易执行:
#!/usr/bin/perl
# Get the URL
$url = $ARGV[0];
# Fetch the header
$header = `curl $url --head --silent`;
# Try to find the status code
$header =~ m/(\d{3})/;
# Return the result
exit(0) if $1 == 404;
exit(1);
只需将其复制并粘贴到文件中即可。在此示例中,我将文件命名为url_check
。然后使用以下命令使文件可执行:
chmod 755 url_check
然后您可以使用以下简单命令检查任何文件:
./url_检查[网址]
如果服务器返回 404,则返回值为“0”,否则返回值为“1”。然后,您可以像执行任何其他命令一样在 shell 中链接此命令。
答案3
wget http://192.168.1.1/backup/01012011.zip
结果代码 0 表示是,否则表示否。
您可以使用变量检查脚本内的结果代码$?
。