将cat的输出管道传输到cURL以下载文件列表


83

我在名为的文件中有一个列表网址urls.txt。每行包含1个URL。我想使用cURL一次下载所有文件。我似乎无法找到合适的单线。

我试过了:

$ cat urls.txt | xargs -0 curl -O

但这只给了我列表中的最后一个文件。


10
for i in $(cat urls.txt) ; do curl -O $i ; done
bkconrad

1
谢谢,@ bkconrad。我在Windows上的换行符有问题,我用以下方法解决了trfor i in $(cat urls.txt) ; do curl -O $(echo $i | tr '\r' ' ') ; done
biphobe

Answers:


138

这对我有用:

$ xargs -n 1 curl -O < urls.txt

我在FreeBSD中。您的xargs可能会有所不同。

请注意,这会连续运行curls,您可能会认为它们不必要地繁重。如果您想节省一些开销,可以在bash中使用以下方法:

$ mapfile -t urls < urls.txt
$ curl ${urls[@]/#/-O }

这会将您的URL列表保存到一个数组,然后使用选项扩展该数组curl以导致下载目标。该curl命令可以采用多个URL并提取所有URL,从而回收现有连接(HTTP / 1.1),但是-O在每个URL之前都需要使用该选项才能下载和保存每个目标。请注意,可能需要对某些URL中的字符进行转义,以避免与您的shell进行交互。

或者,如果您使用的是POSIX Shell而不是bash:

$ curl $(printf ' -O %s' $(cat urls.txt))

这依赖于printf重复格式模式以耗尽数据参数列表的行为。并非所有独立服务器printf都可以做到这一点。

请注意,对于非常大的URL列表,此非xargs方法也可能会违反系统限制。如果这是一个问题,请研究ARG_MAXMAX_ARG_STRLEN


这似乎可行,但是只给了我一个125字节的HTML文件,其中包含文件名,而不是实际文件内容。
芬奇2012年

1
知道了 涉及到重定向,因此我需要将-L选项添加到中curl
芬奇2012年

4
感谢您的提示!可以在Mac上运行,但我更喜欢管道版本cat urls.txt | xargs -n 1 curl -O;-)
orzechow 2014年

@Pio,很公平,它都可以工作,但是为了您的阅读乐趣,unix.stackexchange.com
questions /

这很棒!但是我在Windows上的git bash中使用了它,它不喜欢\r文本文件中的字符。
James McDonnell

33

一个非常简单的解决方案如下:如果您有一个文件'file.txt',例如

url="http://www.google.de"
url="http://www.yahoo.de"
url="http://www.bing.de"

然后您可以使用curl并简单地做

curl -K file.txt

curl会调用您file.txt中包含的所有Urls!

因此,如果您可以控制输入文件格式,那么这也许是最简单的解决方案!


1
这会使用HTTP保持活动状态吗?
William Entriken '17

@FullDecent它以这种方式重用连接
Allan Deamon

14

或者您可以这样做:

cat urls.txt | xargs curl -O

-I当要将cat输出插入命令中间时,才需要使用参数。


1
不知道为什么将其否决,但是它对我来说效果很好,但是我输入的不是grep输出,而是平面文本文件。

1
可能因为不对而被否决了。该-o用于卷曲选项指定输出文件作为其参数。其他答案建议-O,它告诉curl根据文件的远程名称确定本地名称。
ghoti 2015年

8

xargs -P 10 | curl

GNUxargs -P可以curl并行运行多个进程。例如运行 10流程:

xargs -P 10 -n 1 curl -O < urls.txt

如果未达到最大下载速度,并且服务器没有限制IP,这将加快10倍的下载速度,这是最常见的情况。

只是不要设置-P得太高,否则您的RAM可能会不堪重负。

GNUparallel可以达到类似的结果。

这些方法的缺点是它们不对所有文件使用单个连接,curl如果您一次将多个URL传递给它,该怎么办:

curl -O out1.txt http://exmple.com/1 -O out2.txt http://exmple.com/2

/server/199434/how-do-i-make-curl-use-keepalive-from-the-command-line所述

也许将两种方法结合起来可以得到最好的结果?但是我认为并行化比保持连接有效更为重要。

另请参阅:使用Curl命令行实用程序并行下载


7

这是我在Mac(OSX)上的操作方式,但在其他系统上也应同样有效:

您需要一个包含curl链接的文本文件

像这样:

    http://www.site1.com/subdirectory/file1-[01-15].jpg
    http://www.site1.com/subdirectory/file2-[01-15].jpg
    .
    .
    http://www.site1.com/subdirectory/file3287-[01-15].jpg

在这种情况下,文本文件有3287行,每行编码15张图片。

假设我们将这些链接保存在硬盘顶级(/)上名为testcurl.txt的文本文件中。

现在我们必须进入终端并在bash shell中输入以下命令:

    for i in "`cat /testcurl.txt`" ; do curl -O "$i" ; done

确保您使用的是反勾号(`),并且还请确保标志(-O)为大写字母O,而不是零

带有-O标志,将采用原始文件名

下载愉快!


您应该引用您的变量引用。如果有人在您的文本文件中植入了带有特殊字符的文件怎么办?添加一行,echo ";sudo rm -rf ~/" >> testcurl.txt然后看看会发生什么。
ghoti

4
^如果您不知道,请不要这样做。
里克·汉隆

2
这是一个可怕的解决方案。它不仅会为每次下载生成单独的进程,而且还必须每次都重新建立TCP连接,甚至在中等延迟的网络上也浪费了很多时间。
cnst

4

正如其他人正确提到的:

-cat urls.txt | xargs -0 curl -O
+cat urls.txt | xargs -n1 curl -O

但是,这种模式是一个非常糟糕的主意,尤其是如果所有URL都来自同一服务器时-您不仅会产生另一个curl实例,还将为每个请求建立一个新的TCP连接,是非常低效的,对于现在无处不在的https来说效率更高。

请改用此:

-cat urls.txt | xargs -n1 curl -O
+cat urls.txt | wget -i/dev/fd/0

或者,甚至更简单:

-cat urls.txt | wget -i/dev/fd/0
+wget -i/dev/fd/0 < urls.txt

最简单的:

-wget -i/dev/fd/0 < urls.txt
+wget -iurls.txt

2
OP特别是关于如何使用curl做到这一点。也许这是在已经安装curl而不是wget的系统上使用的,例如OSX。另外,不需要依赖devfs,也可以使用它-i-来引用stdin。即:wget -i- < urls.txt最后,如果您想curl一次请求多个URL,而无需重新生成,则始终可以将它们放在命令行中。 xargs curl < urls.txt使用HTTP / 1.1完成此操作。URL的数量受到xargs可以处理的命令行长度的限制。找出此限制getconf ARG_MAX
ghoti 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.