Виведіть патрубок cat на cURL, щоб завантажити список файлів


84

У мене є список URL-адрес у файлі, який називається urls.txt. Кожен рядок містить 1 URL-адресу. Я хочу завантажити всі файли одночасно за допомогою cURL. Здається, я не можу дістати правильний однокласник.

Я намагався:

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

Але це дає мені лише останній файл у списку.


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

1
Дякую, @bkconrad. У мене були проблеми з новими рядками в Windows, я виправив це за допомогою tr:for i in $(cat urls.txt) ; do curl -O $(echo $i | tr '\r' ' ') ; done
biphobe 02

Відповіді:


138

Це працює для мене:

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

Я у FreeBSD. Ваші ксарги можуть працювати по-різному.

Зверніть увагу, що це запускає послідовні curls, які ви можете розглядати як надмірно важкі. Якщо ви хочете зберегти частину цих накладних витрат, у bash може працювати наступне:

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

Це зберігає ваш список URL-адрес у масиві, а потім розширює масив опціями, curlщоб викликати завантаження цілей. curlКоманда може взяти кілька URL - адрес і витягти всі з них, рециркуляції існуючого з'єднання (HTTP / 1.1), але вона потребує -Oопції перед кожними з них для того , щоб завантажити і зберегти кожну мету. Зверніть увагу, що символи в деяких URL-адресах], можливо, доведеться уникати, щоб уникнути взаємодії з вашою оболонкою.

Або якщо ви використовуєте оболонку POSIX, а не bash:

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

Це покладається на printfповедінку користувача при повторенні шаблону форматування, щоб вичерпати список аргументів даних; не всі самостійні printfце зроблять.

Зауважте, що цей метод, не пов’язаний з xargs, також може зіткнутися з обмеженнями системи для дуже великих списків URL-адрес. Дослідження ARG_MAX і MAX_ARG_STRLEN , якщо це є проблемою.


Здається, це працює, але це дає мені лише 125-байтний HTML-файл, що містить ім’я файлу, а не фактичний вміст файлу.
Фінч

1
А, бачу. Було перенаправлення, тому мені потрібно було додати -Lопцію до curl.
Фінч

4
Дякую за підказку! Це працює на моєму Mac, але я віддаю перевагу конвеєрній версії cat urls.txt | xargs -n 1 curl -O;-)
orzechow

@Pio, досить справедливо, все це працює, але для вашого задоволення читання, unix.stackexchange.com/questions/16279 / ...
Ghoti

Це чудово працювало !. Однак я використовував це в git bash у вікнах, і мені не подобалися \rсимволи в текстовому файлі.
James McDonnell

34

Дуже простим рішенням буде наступне: Якщо у вас є файл "file.txt", наприклад

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

Тоді ви можете використовувати завивку і просто зробити

curl -K file.txt

І curl буде викликати всі URL-адреси, що містяться у вашому файлі file.txt!

Отже, якщо ви маєте контроль над форматом вхідного файлу, можливо, це найпростіше рішення для вас!


1
Чи буде це використовувати HTTP для збереження життя?
Вільям Ентрікен

@FullDecent Він повторно використовує зв’язок таким чином
Аллан Дімон,

14

Або ви можете просто зробити це:

cat urls.txt | xargs curl -O

Вам потрібно використовувати -Iпараметр лише тоді, коли ви хочете вставити вихідні дані cat в середині команди.


1
не впевнений, чому це голосування відхилено, але для мене це ідеально працює, але замість простого текстового файлу для введення я отримав вихід grep.
грабуйте

1
Можливо, проголосували проти, бо це неправильно. -oВаріант для завитка визначає вихідний файл в якості аргументу. Інші відповіді рекомендують -O, що вказує curl для визначення локального імені на основі віддаленого імені файлу.
ghoti

8

xargs -P 10 | curl

GNU xargs -Pможе паралельно запускати кілька curlпроцесів. Наприклад, для запуску 10процесів:

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

Це прискорить завантаження в 10 разів, якщо ваша максимальна швидкість завантаження, якщо її не досягнуто, і якщо сервер не обмежує IP-адреси, є найбільш поширеним сценарієм.

Тільки не встановлюйте -Pзанадто високо, інакше ваша оперативна пам’ять може бути перевантажена.

GNU parallelможе досягти подібних результатів.

Недоліком цих методів є те, що вони не використовують єдине з’єднання для всіх файлів, що і 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), але це має однаково добре працювати в інших системах:

Вам потрібен текстовий файл, що містить посилання для завивки

подобається так:

    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

4
^ Якщо ви не знаєте, не робіть цього.
Рік Хенлон II,

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
ОП конкретно стосувався того, як це зробити за допомогою завивки. Можливо, це для використання в системі, де 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.