web-dev-qa-db-fra.com

Pipe la sortie du chat à cURL pour télécharger une liste de fichiers

J'ai une liste d'URL dans un fichier nommé urls.txt. Chaque ligne contient 1 URL. Je souhaite télécharger tous les fichiers simultanément à l'aide de cURL. Je n'arrive pas à obtenir le bon one-line.

J'ai essayé:

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

Mais cela ne me donne que le dernier fichier de la liste.

72
Finch

Cela fonctionne pour moi:

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

Je suis dans FreeBSD. Vos xargs peuvent fonctionner différemment.

Notez que ceci exécute curls séquentielle, que vous pouvez considérer comme inutilement lourde. Si vous souhaitez économiser une partie de cette surcharge, les opérations suivantes peuvent fonctionner dans bash:

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

Cela enregistre votre liste d’URL dans un tableau, puis le développe avec des options à curl pour que les cibles soient téléchargées. La commande curl peut prendre plusieurs URL et les extraire toutes, en recyclant la connexion existante (HTTP/1.1), mais elle nécessite le -O avant chaque option pour télécharger et sauvegarder chaque cible.

Ou si vous utilisez un shell POSIX plutôt que bash:

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

Cela repose sur le comportement de printf consistant à répéter le modèle de format pour épuiser la liste des arguments de données; ce ne sont pas tous les printfs autonomes qui le feront.

Notez que cette méthode non-xargs peut également se heurter aux limites système imposées par les très grandes listes d'URL. Recherche ARG_MAX et MAX_ARG_STRLEN s'il s'agit d'un problème.

127
ghoti

Une solution très simple serait la suivante: Si vous avez un fichier 'file.txt' comme

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

Ensuite, vous pouvez utiliser curl et simplement faire

curl -K file.txt

Et curl appellera toutes les URL contenues dans votre fichier.txt!

Donc, si vous avez le contrôle sur votre format de fichier d’entrée, c’est peut-être la solution la plus simple pour vous!

26
Dirk

Ou vous pouvez simplement faire ceci:

cat urls.txt | xargs curl -O

Vous devez seulement utiliser le -I paramètre lorsque vous souhaitez insérer la sortie cat au milieu d’une commande.

12
user1101791

xargs -P 10 | curl

GNU xargs -P peut exécuter plusieurs processus curl en parallèle. Par exemple. courir 10 processus:

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

Cela accélérera le téléchargement 10x si votre vitesse de téléchargement maximale n'est pas atteinte et si le serveur ne réduit pas les adresses IP, ce qui est le scénario le plus courant.

Il suffit de ne pas définir -P trop haut ou votre RAM peut être dépassé.

GNU parallel peut atteindre des résultats similaires.

L'inconvénient de ces méthodes est qu'elles n'utilisent pas une seule connexion pour tous les fichiers, ce que fait curl si vous lui transmettez plusieurs URL en même temps, comme dans:

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

comme mentionné à https://serverfault.com/questions/199434/how-do-i-make-curl-use-keepalive-from-the-command-line

Peut-être que combiner les deux méthodes donnerait les meilleurs résultats? Mais j'imagine que la parallélisation est plus importante que de maintenir la connexion en vie.

Voir aussi: téléchargement parallèle à l'aide de l'utilitaire de ligne de commande Curl

Voici comment je le fais sur un Mac (OSX), mais cela devrait fonctionner aussi bien sur d'autres systèmes:

Ce dont vous avez besoin est un fichier texte contenant vos liens pour curl

ainsi:

    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

Dans ce cas hypothétique, le fichier texte contient 3287 lignes et chaque ligne code pour 15 images.

Supposons que nous sauvegardons ces liens dans un fichier texte appelé testcurl.txt au niveau supérieur (/) de notre disque dur.

Nous devons maintenant entrer dans le terminal et entrer la commande suivante dans le shell bash:

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

Assurez-vous d’utiliser les ticks arrière (`). Assurez-vous également que le drapeau (-O) est un O majuscule et NON un zéro.

avec le drapeau -O, le nom de fichier d'origine sera pris

Bon téléchargement!

7
Stefan Gruenwald

Comme d'autres l'ont mentionné à juste titre:

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

Cependant, ce paradigme est une très mauvaise idée, en particulier si toutes vos URL proviennent du même serveur. Vous créerez non seulement une autre instance curl, mais vous créerez également un nouveau TCP connexion pour chaque demande, ce qui est très inefficace, et plus encore avec le https maintenant omniprésent.

Veuillez utiliser ceci à la place:

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

Ou encore plus simple:

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

Le plus simple à ce jour:

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