Dosya listesini indirmek için cat'den cURL'ye boru çıkışı


84

Adlı bir dosyada URL'lerin bir listesi var urls.txt. Her satır 1 URL içerir. CURL kullanarak tüm dosyaları bir kerede indirmek istiyorum. Doğru tek sırayı indiremiyorum.

Denedim:

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

Ama bu bana sadece listedeki son dosyayı veriyor.


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

1
Teşekkürler @bkconrad. Yine de Windows'ta yeni satırlarla ilgili sorunlar yaşadım, bunu şu şekilde düzelttim tr:for i in $(cat urls.txt) ; do curl -O $(echo $i | tr '\r' ' ') ; done
biphobe

Yanıtlar:


138

Bu benim için çalışıyor:

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

FreeBSD'deyim. Xarglarınız farklı çalışabilir.

Bunun curlgereksiz yere ağır olarak görebileceğiniz sıralı e'leri çalıştırdığını unutmayın . Bu ek yükün bir kısmını kurtarmak isterseniz, bash'da aşağıdakiler işe yarayabilir:

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

Bu, URL listenizi bir diziye kaydeder, ardından curlhedeflerin indirilmesine neden olmak için diziyi seçeneklerle genişletir . curlKomut birden fazla URL almak ve mevcut bağlantı (HTTP / 1.1) geri dönüşüm, hepsini getir, ama bu ihtiyacı olabilir -Oiçin her biri önce seçeneği indirme ve kaydetme her bir hedef. Kabuğunuzla etkileşimden kaçınmak için bazı URL'lerdeki] karakterlerin öncelenmesi gerekebileceğini unutmayın.

Veya bash yerine bir POSIX kabuğu kullanıyorsanız:

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

Bu printf, veri bağımsız değişkenlerinin listesini tüketmek için biçim örüntüsünü tekrarlama davranışına dayanır ; tek başına printfçalışanların hepsi bunu yapmaz.

Bu xargs olmayan yöntemin çok büyük URL listeleri için sistem sınırlarını da aşabileceğini unutmayın. Araştırma ARG_MAX ve MAX_ARG_STRLEN bu bir endişe ise.


Bu işe yarıyor gibi görünüyor, ancak bana gerçek dosya içeriğini değil , yalnızca dosyanın adını içeren 125 baytlık bir HTML dosyası veriyor .
Finch

1
Ah, anlıyorum. Bir yönlendirme vardı, bu yüzden -Lseçeneği eklemem gerekiyordu curl.
Finch

4
İpucu için teşekkürler! Thats my Mac üzerinde çalışıyor, ama boru hattı versiyonunu tercih cat urls.txt | xargs -n 1 curl -O;-)
orzechow

@Pio, yeterince adil, hepsi işe yarıyor, ancak okuma zevkiniz için, unix.stackexchange.com/questions/16279/…
ghoti

Bu harika çalıştı !. Ancak bunu pencerelerde git bash'da kullandım \rve metin dosyasındaki karakterlerden hoşlanmadı .
James McDonnell

34

Çok basit bir çözüm şu olabilir: "file.txt" gibi bir dosyanız varsa

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

O zaman curl kullanabilir ve basitçe yapabilirsiniz

curl -K file.txt

Ve curl, file.txt dosyanızda bulunan tüm URL'leri çağıracaktır!

Dolayısıyla, girdi dosya biçiminiz üzerinde kontrole sahipseniz, belki bu sizin için en basit çözümdür!


1
Bu, HTTP canlı tutma özelliğini kullanacak mı?
William Entriken

@FullDecent Bağlantıyı bu şekilde yeniden kullanıyor
Allan Deamon

14

Ya da bunu yapabilirsin:

cat urls.txt | xargs curl -O

-IParametreyi yalnızca cat çıktısını bir komutun ortasına eklemek istediğinizde kullanmanız gerekir .


1
bunun neden reddedildiğinden emin değilim ama benim için mükemmel çalışıyor, ancak girdi için düz bir metin dosyası yerine grep çıktısını aldım.
soymak

1
Muhtemelen yanlış olduğu için olumsuz oy verildi. -oKıvrılma bakımından seçenek onun argüman olarak bir çıkış dosyasını belirtir. Diğer yanıtlar önerilir -O, bu da curl'ye dosyanın uzak adına göre yerel adı belirlemesini söyler.
ghoti

8

xargs -P 10 | curl

GNU xargs -Pbirden çok curlişlemi paralel olarak çalıştırabilir . Örneğin 10süreçleri çalıştırmak için :

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

Bu, en yaygın senaryo olan maksimum indirme hızınıza ulaşılmazsa ve sunucu IP'leri kısıtlamazsa indirmeyi 10 kat hızlandıracaktır.

Sadece -Pçok yükseğe ayarlamayın, yoksa RAM'iniz boğulmuş olabilir.

GNU parallelbenzer sonuçlar elde edebilir.

Bu yöntemlerin dezavantajı onlar neyi tüm dosyalar için tek bir bağlantı kullanmak kalmamasıdır curlnda olduğu gibi bir defada buna birden fazla URL geçirirseniz yapar:

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 adresinde belirtildiği gibi

Belki her iki yöntemi birleştirmek en iyi sonuçları verir? Ancak paralelleştirmenin bağlantıyı canlı tutmaktan daha önemli olduğunu düşünüyorum.

Ayrıca bkz: Curl komut satırı yardımcı programını kullanarak paralel indirme


7

Mac'te (OSX) bunu nasıl yapıyorum, ancak diğer sistemlerde de eşit derecede iyi çalışması gerekir:

İhtiyacınız olan şey curl için bağlantılarınızı içeren bir metin dosyasıdır

bunun gibi:

    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

Bu varsayımsal durumda, metin dosyası 3287 satıra sahiptir ve her satır 15 resmi kodlamaktadır.

Diyelim ki bu bağlantıları sabit sürücümüzün en üst seviyesinde (/) testcurl.txt adlı bir metin dosyasına kaydettik.

Şimdi terminale girmeli ve bash kabuğuna aşağıdaki komutu girmeliyiz:

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

Geri tikleri kullandığınızdan emin olun (`) Ayrıca bayrağın (-O) büyük harf O olduğundan ve sıfır OLMADIĞINDAN emin olun.

-O işareti ile orijinal dosya adı alınacaktır

Mutlu indirmeler!


Değişken referanslarınızı vermelisiniz. Ya birisi metin dosyanıza özel karakterli bir dosya yerleştirdiyse? Bir satır ekleyin echo ";sudo rm -rf ~/" >> testcurl.txtve ne olacağını görün.
ghoti

4
^ Bilmiyorsanız bunu yapmayın.
Rick Hanlon II

2
Bu korkunç bir çözüm; sadece her indirme için ayrı bir süreç oluşturmakla kalmaz, aynı zamanda her seferinde TCP bağlantısını yeniden kurması gerekir ve orta gecikmeli ağlarda bile çok fazla zaman harcar.
cnst

4

Başkalarının haklı olarak belirttiği gibi:

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

Bununla birlikte, bu paradigma çok kötü bir fikirdir, özellikle tüm URL'leriniz aynı sunucudan geliyorsa - yalnızca başka bir curl örneği üretmeyeceksiniz, aynı zamanda her istek için yeni bir TCP bağlantısı kuracaksınız. son derece verimsiz ve hatta artık her yerde bulunan https ile daha da fazla.

Lütfen bunun yerine şunu kullanın:

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

Veya daha da basit:

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

Şimdiye kadarki en basit:

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

2
OP özellikle bunun curl ile nasıl yapılacağıyla ilgiliydi. Belki de bu, curl'nin zaten kurulu olduğu ancak wget'in yüklü olmadığı bir sistemde, örneğin OSX'te kullanım içindir. Ayrıca, devflere bağlı olmanıza gerek yoktur, stdin'e -i-başvurmak için de kullanabilirsiniz . Yani: wget -i- < urls.txtSon olarak, curlaynı anda birden fazla URL talep etmek istiyorsanız , yeniden doğmaya gerek kalmadan, bunları her zaman komut satırına koyabilirsiniz. xargs curl < urls.txtbunu HTTP / 1.1 kullanarak yapar. Xargs'ın işleyebileceği komut satırı uzunluğuyla URL'lerin sayısı sınırlıdır. Bu sınırı ile öğrenin getconf ARG_MAX.
ghoti
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.