Đầu ra đường ống của mèo sang cURL để tải xuống danh sách các tệp


83

Tôi có một danh sách URL trong một tệp được gọi là urls.txt. Mỗi dòng chứa 1 URL. Tôi muốn tải xuống tất cả các tệp cùng một lúc bằng cURL. Tôi dường như không thể lấy đúng một lớp lót.

Tôi đã thử:

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

Nhưng điều đó chỉ mang lại cho tôi tệp cuối cùng trong danh sách.


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

1
Cảm ơn, @bkconrad. Tôi có vấn đề với dòng mới trên Windows, mặc dù tôi cố định nó với tr:for i in $(cat urls.txt) ; do curl -O $(echo $i | tr '\r' ' ') ; done
biphobe

Câu trả lời:


138

Điều này phù hợp với tôi:

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

Tôi đang ở FreeBSD. Xargs của bạn có thể hoạt động khác nhau.

Lưu ý rằng điều này chạy các curls tuần tự , mà bạn có thể xem là nặng không cần thiết. Nếu bạn muốn tiết kiệm một số chi phí đó, những điều sau có thể hoạt động trong bash:

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

Thao tác này sẽ lưu danh sách URL của bạn vào một mảng, sau đó mở rộng mảng với các tùy chọn để curltải xuống các mục tiêu. Các curllệnh có thể mất nhiều URL và lấy tất cả trong số họ, tái chế các kết nối hiện tại (HTTP / 1.1), nhưng nó cần các -Otùy chọn trước mỗi một để tải về và tiết kiệm mỗi mục tiêu. Lưu ý rằng các ký tự trong một số URL] có thể cần được thoát ra để tránh tương tác với trình bao của bạn.

Hoặc nếu bạn đang sử dụng trình bao POSIX thay vì bash:

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

Điều này dựa vào printfhành vi lặp lại mẫu định dạng để làm cạn kiệt danh sách các đối số dữ liệu; không phải tất cả độc lập printfsẽ làm điều này.

Lưu ý rằng phương pháp không phải xargs này cũng có thể vượt quá giới hạn hệ thống đối với danh sách URL rất lớn. Nghiên cứu ARG_MAXMAX_ARG_STRLEN nếu đây là mối quan tâm.


Điều này có vẻ hoạt động, nhưng nó chỉ cung cấp cho tôi một tệp HTML 125 byte chứa tên của tệp, không phải nội dung tệp thực.
Finch

1
Ah tôi thấy. Có một chuyển hướng liên quan nên tôi cần thêm -Ltùy chọn vào curl.
Finch

4
Cảm ơn vì gợi ý! Thats làm việc trên máy Mac của tôi, nhưng tôi thích phiên bản đường ống cat urls.txt | xargs -n 1 curl -O;-)
orzechow

@Pio, công bằng mà nói, tất cả đều hoạt động, nhưng vì niềm vui đọc của bạn, unix.stackexchange.com/questions/16279/…
ghoti

Điều này làm việc tuyệt vời !. Tuy nhiên, tôi đã sử dụng điều này trong git bash trên windows và nó không thích các \rký tự trong tệp văn bản.
James McDonnell

34

Một giải pháp rất đơn giản sẽ như sau: Nếu bạn có tệp 'file.txt' như

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

Sau đó, bạn có thể sử dụng cuộn tóc và chỉ cần làm

curl -K file.txt

Và curl sẽ gọi tất cả các Url có trong file.txt của bạn!

Vì vậy, nếu bạn có quyền kiểm soát định dạng tệp đầu vào của mình, có lẽ đây là giải pháp đơn giản nhất cho bạn!


1
Điều này sẽ sử dụng HTTP duy trì tồn tại?
William Entriken

@FullDecent Nó reuses kết nối theo cách này
Allan Deamon

14

Hoặc bạn chỉ có thể làm điều này:

cat urls.txt | xargs curl -O

Bạn chỉ cần sử dụng -Itham số khi muốn chèn đầu ra con mèo vào giữa một lệnh.


1
không chắc tại sao điều này bị bỏ phiếu nhưng nó hoạt động hoàn hảo đối với tôi, nhưng thay vì một tệp văn bản phẳng cho đầu vào, tôi đã có đầu ra là grep.
cướp

1
Có thể bị phản đối vì nó sai. Các -olựa chọn cho curl xác định một tập tin đầu ra như là đối số của nó. Các câu trả lời khác khuyến nghị -O, nó cho curl biết để xác định tên cục bộ dựa trên tên từ xa của tệp.
ghoti

8

xargs -P 10 | curl

GNU xargs -Pcó thể chạy curlsong song nhiều tiến trình. Ví dụ: chạy 10các quy trình:

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

Điều này sẽ tăng tốc độ tải xuống gấp 10 lần nếu tốc độ tải xuống tối đa của bạn nếu không đạt được và nếu máy chủ không điều chỉnh IP, đây là trường hợp phổ biến nhất.

Chỉ cần không đặt -P quá cao nếu không RAM của bạn có thể bị quá tải.

GNU parallel có thể đạt được kết quả tương tự.

Nhược điểm của các phương pháp đó là chúng không sử dụng một kết nối duy nhất cho tất cả các tệp, điều curlnày sẽ xảy ra nếu bạn chuyển nhiều URL đến nó cùng một lúc như trong:

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

như đã đề cập tại /server/199434/how-do-i-make-curl-use-keepalive-from-the-command-line

Có thể kết hợp cả hai phương pháp sẽ cho kết quả tốt nhất? Nhưng tôi tưởng tượng rằng song song hóa quan trọng hơn là giữ cho kết nối tồn tại.

Xem thêm: Tải song song bằng tiện ích dòng lệnh Curl


7

Đây là cách tôi thực hiện trên máy Mac (OSX), nhưng nó sẽ hoạt động tốt như nhau trên các hệ thống khác:

Những gì bạn cần là một tệp văn bản chứa các liên kết của bạn để cuộn

như vậy:

    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

Trong trường hợp giả định này, tệp văn bản có 3287 dòng và mỗi dòng mã hóa cho 15 hình ảnh.

Giả sử chúng tôi lưu các liên kết này trong một tệp văn bản có tên là testcurl.txt trên cấp cao nhất (/) của ổ cứng.

Bây giờ chúng ta phải vào terminal và nhập lệnh sau vào bash shell:

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

Đảm bảo rằng bạn đang sử dụng dấu tích ngược (`) Đồng thời đảm bảo rằng cờ (-O) là chữ O viết hoa chứ KHÔNG phải là số 0

với cờ -O, tên tệp gốc sẽ được sử dụng

Chúc bạn tải xuống vui vẻ!


Bạn nên trích dẫn các tham chiếu biến của bạn. Điều gì sẽ xảy ra nếu ai đó đã đặt một tệp có ký tự đặc biệt vào tệp văn bản của bạn? Thêm một dòng echo ";sudo rm -rf ~/" >> testcurl.txtvà xem điều gì sẽ xảy ra.
ghoti,

4
^ Nếu bạn không biết, đừng làm điều này.
Rick Hanlon II

2
Đây là một giải pháp kinh khủng; nó không chỉ tạo ra một quá trình riêng biệt cho mỗi lần tải xuống mà còn phải thiết lập lại kết nối TCP mỗi lần, gây lãng phí rất nhiều thời gian trên các mạng có độ trễ trung bình.
cnst

4

Như những người khác đã đề cập đúng:

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

Tuy nhiên, mô hình này là một ý tưởng rất tồi, đặc biệt nếu tất cả các URL của bạn đến từ cùng một máy chủ - bạn không chỉ tạo ra một phiên bản curl khác mà còn thiết lập một kết nối TCP mới cho mỗi yêu cầu, rất kém hiệu quả và thậm chí còn hơn thế nữa với https hiện nay phổ biến.

Vui lòng sử dụng cái này thay thế:

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

Hoặc đơn giản hơn nữa:

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

Đơn giản nhất:

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

2
OP đã nói cụ thể về cách làm điều này với tóc xoăn. Có lẽ điều này được sử dụng trên một hệ thống đã cài đặt curl nhưng wget thì không, chẳng hạn như OSX. Ngoài ra, không cần phụ thuộc vào devfs, bạn cũng có thể sử dụng -i-để tham khảo stdin. Tức là: wget -i- < urls.txtCuối cùng, nếu bạn muốn curlyêu cầu nhiều URL cùng lúc mà không yêu cầu hồi sinh, bạn luôn có thể đặt chúng trên dòng lệnh. xargs curl < urls.txtthực hiện điều này, sử dụng HTTP / 1.1. Bạn bị giới hạn về số lượng URL theo độ dài dòng lệnh mà xargs có thể xử lý. Tìm ra giới hạn này với getconf ARG_MAX.
ghoti
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.