如何将字符串列表传递给 xargs 以同时进行 wget
How can I pass a list of strings to xargs for simultaneous wget
我有一个字符串数组(列表),其中包含 url 并附加了自定义目录名称
urls="http://domain.com/book1**Shakespeare http://domain.com/book2**King http://domain.com/book3**Twain"
- 每个字符串的 url 部分(在 ** 之前)请求一个 .zip 文件,我会
喜欢传递给wget。
- 每个字符串的第二部分(在 ** 之后)是我想将 wget 请求中的文件放入的目录
所以最终,我对目录结构的期望是:
/Shakespeare/
book.zip
/King/
book.zip
/Twain/
book.zip
到目前为止我得到的是...
echo $urls | xargs -n 1 -P 8 | sed 's/\*\*.*//'
这正确地输出了我需要 wget 的 5 个 url,没有在每个末尾附加 **author。 (即 http://domain.com/book2**King
变为 http://domain.com/book2
)
现在......我想将这些新的格式正确下载urls传递给wget,同时也以某种方式传递剥离的**author
部分作为 wget destination option
的一部分提供
我使用 "xargs" 的主要原因是因为我已经能够将 url 的列表传递给它并获取它们 同时。我希望我可以在同一个调用中将它们同时下载到不同的目标目录。
你要求的是使用 shell 管道非常尴尬。主要问题是您试图获取一个进程的标准输出 (echo
and/or sed
) 用作 参数 到另一个(wget
)。管道不会在这里帮助你,因为根据设计,这些管道将一个进程的 stdin
连接到另一个进程的 stdout
。这会将工具处理的内容与描述如何处理发生的参数混为一谈。所以管道并不是你真正想要的。
您也许可以使用 sed
或 awk
以及 split
、paste
等工具破解它,但您至少会想要编写完整的 shell 脚本,而不仅仅是管道。但我真的建议使用功能更全的脚本语言,尤其是具有更好的字符串处理能力的脚本语言。您想要的另一件事是能够启动子流程。
这一切都表明 Python 之类的东西是一个不错的选择。这是一个示例实现(经过测试,但不严格),它应该可以满足您的需求。
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)
echo $urls | sed 's/\*\*/ -P /g' | xargs -n 3 -P 8 wget
这应该可以满足您的需求,但更好的方法可能是将逻辑移至上游,即无论您在哪里生成 $urls
。另外,我不清楚您是否需要添加 .zip
。如果是这样,您也可以在 sed
模式中执行此操作。
解释:
wget
可以使用 -P
选项指定 prefix/download 位置。
因此,如果您的 objective 是 运行 每个命令,如下所示:
wget http://domain.com/book1 -P Shakespeare
然后我将首先使用 sed
将每个 **
替换为 -P
,然后使用 -n 3
通过管道传输到 xargs
,因为到时候它到达 xargs
,你想一次传递三个单词到 wget
。
我有一个字符串数组(列表),其中包含 url 并附加了自定义目录名称
urls="http://domain.com/book1**Shakespeare http://domain.com/book2**King http://domain.com/book3**Twain"
- 每个字符串的 url 部分(在 ** 之前)请求一个 .zip 文件,我会 喜欢传递给wget。
- 每个字符串的第二部分(在 ** 之后)是我想将 wget 请求中的文件放入的目录
所以最终,我对目录结构的期望是:
/Shakespeare/
book.zip
/King/
book.zip
/Twain/
book.zip
到目前为止我得到的是...
echo $urls | xargs -n 1 -P 8 | sed 's/\*\*.*//'
这正确地输出了我需要 wget 的 5 个 url,没有在每个末尾附加 **author。 (即 http://domain.com/book2**King
变为 http://domain.com/book2
)
现在......我想将这些新的格式正确下载urls传递给wget,同时也以某种方式传递剥离的**author
部分作为 wget destination option
我使用 "xargs" 的主要原因是因为我已经能够将 url 的列表传递给它并获取它们 同时。我希望我可以在同一个调用中将它们同时下载到不同的目标目录。
你要求的是使用 shell 管道非常尴尬。主要问题是您试图获取一个进程的标准输出 (echo
and/or sed
) 用作 参数 到另一个(wget
)。管道不会在这里帮助你,因为根据设计,这些管道将一个进程的 stdin
连接到另一个进程的 stdout
。这会将工具处理的内容与描述如何处理发生的参数混为一谈。所以管道并不是你真正想要的。
您也许可以使用 sed
或 awk
以及 split
、paste
等工具破解它,但您至少会想要编写完整的 shell 脚本,而不仅仅是管道。但我真的建议使用功能更全的脚本语言,尤其是具有更好的字符串处理能力的脚本语言。您想要的另一件事是能够启动子流程。
这一切都表明 Python 之类的东西是一个不错的选择。这是一个示例实现(经过测试,但不严格),它应该可以满足您的需求。
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)
echo $urls | sed 's/\*\*/ -P /g' | xargs -n 3 -P 8 wget
这应该可以满足您的需求,但更好的方法可能是将逻辑移至上游,即无论您在哪里生成 $urls
。另外,我不清楚您是否需要添加 .zip
。如果是这样,您也可以在 sed
模式中执行此操作。
解释:
wget
可以使用 -P
选项指定 prefix/download 位置。
因此,如果您的 objective 是 运行 每个命令,如下所示:
wget http://domain.com/book1 -P Shakespeare
然后我将首先使用 sed
将每个 **
替换为 -P
,然后使用 -n 3
通过管道传输到 xargs
,因为到时候它到达 xargs
,你想一次传递三个单词到 wget
。