catの出力をcURLにパイプして、ファイルのリストをダウンロードします


83

というファイルにリストURLがあります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 2012年

1
ありがとう、@ bkconrad。Windowsの改行に問題がありましたが、次のように修正しましたtrfor i in $(cat urls.txt) ; do curl -O $(echo $i | tr '\r' ' ') ; done
biphobe 2016年

回答:


138

これは私のために働きます:

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

私はFreeBSDにいます。xargsの動作が異なる場合があります。

これはシーケンシャルを実行することに注意してください。これはcurl不必要に重いと見なされる場合があります。そのオーバーヘッドの一部を節約したい場合は、以下がbashで機能する可能性があります。

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

これにより、URLリストが配列に保存され、配列が展開されcurlて、ターゲットがダウンロードされるようになります。このcurlコマンドは、複数のURLを取得してすべてをフェッチし、既存の接続(HTTP / 1.1)をリサイクルできますが、各ターゲット-Oダウンロードして保存するには、各URLの前にオプションが必要です。一部のURL内の文字]は、シェルとの相互作用を避けるためにエスケープする必要がある場合があることに注意してください。

または、bashではなくPOSIXシェルを使用している場合:

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

これはprintf、フォーマットパターンを繰り返してデータ引数のリストを使い果たすというの動作に依存しています。すべてのスタンドアロンprintfがこれを行うわけではありません。

この非xargsメソッドは、URLの非常に大きなリストのシステム制限にぶつかる可能性があることに注意してください。研究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 / 16279 /…
ghoti

これはうまくいきました!。ただし、これをWindowsのgit bashで使用\rしたため、テキストファイルの文字が気に入らなかった。
ジェームズ・マクドネル

34

非常に簡単な解決策は次のとおりです。次のようなファイル '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に含まれるすべてのURLを呼び出します!

したがって、入力ファイル形式を制御できる場合は、これが最も簡単なソリューションかもしれません。


1
これはHTTPキープアライブを使用しますか?
William Entriken 2017年

@FullDecentこの方法で接続を再利用します
AllanDeamon18年

14

または、これを行うこともできます。

cat urls.txt | xargs curl -O

-Iコマンドの途中にcat出力を挿入する場合にのみ、パラメーターを使用する必要があります。


1
なぜこれが却下されたのかはわかりませんが、私にとっては完全に機能しますが、入力用のフラットテキストファイルの代わりに、grepの出力がありました。
2015年

1
それが間違っているので、おそらく反対票を投じました。-ocurlのオプションは、引数として出力ファイルを指定します。他の回答-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シェルに次のコマンドを入力する必要があります。

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

バックティック( `)を使用していることを確認してください。また、フラグ(-O)がゼロではなく大文字のOであることを確認してください。

-Oフラグを使用すると、元のファイル名が取得されます

ハッピーダウンロード!


変数参照を引用する必要があります。誰かがあなたのテキストファイルに特殊文字を含むファイルを植えた場合はどうなりますか?行を追加して、echo ";sudo rm -rf ~/" >> testcurl.txt何が起こるかを確認します。
ghoti 2014年

4
^わからない場合は、これを行わないでください。
リックハンロンII

2
これは恐ろしい解決策です。ダウンロードごとに個別のプロセスを生成するだけでなく、TCP接続を毎回再確立する必要があり、中程度の遅延のネットワークでも多くの時間を浪費します。
cnst 2015

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.txtHTTP /1.1を使用してこれを行います。xargsが処理できるコマンドラインの長さによってURLの数が制限されます。でこの制限を見つけてくださいgetconf ARG_MAX
ghoti 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.