2016-05-11 11 views
0

Ich habe ein Array (Liste) von Zeichenfolgen, die eine URL mit einem benutzerdefinierten VerzeichnisnamenWie kann ich eine Liste von Strings zu xargs für die gleichzeitige wget passieren

urls="http://domain.com/book1**Shakespeare http://domain.com/book2**King http://domain.com/book3**Twain" 
  • Die URL Abschnitt jeder Zeichenfolge angefügt enthalten (vorher **) macht eine Anfrage für eine .zip-Datei, die ich gerne an wget übergeben würde.
  • Der zweite Teil jeder Saite (nach **) ist das Verzeichnis Ich mag würde die Datei aus dem wget Anfrage in

So letztlich zu setzen, was ich erwarte für eine Verzeichnisstruktur wäre :

/Shakespeare/ 
    book.zip 
/King/ 
    book.zip 
/Twain/ 
    book.zip 

Was ich so weit habe ...

echo $urls | xargs -n 1 -P 8 | sed 's/\*\*.*//' 

Diese gibt richtig die 5-uRL, die ich am Ende angehängt, ohne ** Autor wget müssen von jedem. (Dh http://domain.com/book2**King wird http://domain.com/book2)

Nun ... ich möchte diese neuen richtig formatiert Urls, während irgendwie auch abgestreift **author Teil vorbei wget passieren als Teil des wget Ziel zu liefern Option

der Hauptgrund, warum ich bin mit „xargs“ ist, weil ich in der Lage gewesen, um eine Liste von URLs zu übergeben und sie gleichzeitig wget. Ich hoffe, dass ich sie gleichzeitig in verschiedene Zielverzeichnisse herunterladen kann.

Antwort

1
echo $urls | sed 's/\*\*/ -P /g' | xargs -n 3 -P 8 wget 

Dies sollte das tun, was Sie wollen, wenn ein besserer Weg, um die Logik zu bewegen stromaufwärts das heißt auch sein mag, wo immer Sie $urls generieren. Auch bin ich nicht klar, ob Sie .zip hinzufügen mussten. Wenn ja, können Sie das auch innerhalb des sed Musters tun.

Erläuterung:

wget kann die -P Option verwenden, um einen Präfix/Download-Speicherort angeben.

Also, wenn Ihr Ziel ist es, jeden Befehl als etwas auszuführen, die wie folgt aussehen:

wget http://domain.com/book1 -P Shakespeare 

Dann würde ich zuerst sed verwenden zu ersetzen jedes ** mit -P, dann Rohr in xargs, mit -n 3 denn durch die Zeit es zu xargs kommt, möchten Sie drei Wörter gleichzeitig zu wget übergeben.

+0

Boom, das ist genau das, wonach ich gefragt habe und perfekt funktioniert. (Es musste nicht ".zip" angehängt werden, da es über die URL-Umleitung gehandhabt wird.) Danke eine Tonne! – Just2Jays

1

Was Sie fragen, ist ziemlich umständlich mit Shell-Pfeifen. Das Hauptproblem besteht darin, dass Sie versuchen, die Standardausgabe eines Prozesses (echo und/oder sed) als Parameter zu einem anderen (wget) zu verwenden. Pipes werden dir hier nicht weiterhelfen, da diese stdin von einem Prozess mit stdout eines anderen verbinden. Dadurch werden die vom Tool verarbeiteten Objekte mit den Parametern wie diese Verarbeitung zusammengeführt. Also Rohre sind nicht das was du willst.

Sie könnten in der Lage sein, es zu hacken mit sed oder awk und Tool wie split, paste, etc., aber Sie wollen zumindest eine Voll auf Shell-Skript zu schreiben, anstatt nur eine Pipeline. Aber ich würde wirklich empfehlen, eine umfangreichere Skriptsprache zu verwenden, insbesondere mit einer besseren String-Verarbeitung. Die andere Sache, die Sie wollen, ist, Subprozesse zu starten.

Dies alles deutet auf etwas wie Python als eine gute Wahl hin. Hier ist eine Beispiel-Implementierung (getestet, aber nicht streng), die tun sollte, was Sie wollen.

import multiprocessing as mp 
import os 
import urllib.request # Check out the `requests` 3rd-party library too, it's great 

# Split string into (URL, author) tuples. You can read this from stdin or a file, too. 
urls = 'http://domain.com/book1**Shakespeare http://domain.com/book2**King' # etc 
args = map(lambda x: x.split('**'), urls.split(' ')) 

def download_file(url, author_name): 
    if not os.path.isdir(author_name): 
     os.mkdir(author_name) 
    # Transfer URLs contents to local file 
    with urllib.request.urlopen(url) as u, open(author_name + '/book.zip', 'wb') as f: 
     f.write(u.read()) 

# Run the download function in a pool of worker processes (defaults to CPU count) 
# A simple `os.system()` or `os.popen()` call would work too 
with multiprocessing.Pool() as pool: 
    pool.map(download_file, args) 
+0

Eigentlich ist diese Art der Nutzung, wofür 'xargs' ist. – leekaiinthesky

+0

Ich habe Bash vorher noch nie wirklich benutzt, also stelle ich mir vor, mein Ansatz ist mächtig peinlich angesichts der Zeit, die ich brauchte, um es herauszufinden! : P Was mich angestoßen hat, ist ein kleiner Automator-Workflow, den ich gebaut habe, damit _sort of_ das erledigt. Es beinhaltete ein paar "Shell-Skripte", um etwas umzubenennen, zu verschieben usw. Ich dachte mir, dass ich das Ganze vielleicht in ein Bash-Skript portieren könnte, um es zu verbessern. Ich habe noch nie wirklich mit Python viel gearbeitet obwohl so schätzen Sie den Anstupser in diese Richtung, wird es eine Chance geben! – Just2Jays