如何将字符串列表传递给 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"

所以最终,我对目录结构的期望是:

/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。这会将工具处理的内容与描述如何处理发生的参数混为一谈。所以管道并不是你真正想要的。

您也许可以使用 sedawk 以及 splitpaste 等工具破解它,但您至少会想要编写完整的 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