如何根据 shell 查找结果添加 argparse 标志
Posted
技术标签:
【中文标题】如何根据 shell 查找结果添加 argparse 标志【英文标题】:How to add argparse flags based on shell find results 【发布时间】:2018-07-05 06:11:47 【问题描述】:我有一个接受-f
标志的python 脚本,并附加了该标志的多种用途。
例如,如果我运行python myscript -f file1.txt -f file2.txt
,我会得到一个文件列表files=['file1.txt', 'files2.txt']
。这很好用,但我想知道如何自动使用 find 命令的结果来附加与文件一样多的 -f
标志。
我试过了:
find ./ -iname '*.txt' -print0 | xargs python myscript.py -f
但它只抓取第一个文件
【问题讨论】:
使用glob.glob方法直接搜索python脚本中的所有文件名不是更容易吗? 您是在问如何从 Python 执行此操作,还是从 shell 执行此操作? 【参考方案1】:需要注意的是,如果文件多于单个命令行,这将失败(而xargs
将运行myscript.py
多次,每次都带有完整参数列表的一个子集):
#!/usr/bin/env bash
args=( )
while IFS= read -r -d '' name; do
args+=( -f "$name" )
done < <(find . -iname '*.txt' -print0)
python myscript.py "$args[@]"
如果您想安全地以允许任意数量的文件名的方式执行此操作,最好使用长格式选项 - 例如 --file
而不是 @987654325 @ -- 使用 =
分隔符允许将单个名称作为同一 argv 条目的一部分传递,从而防止 xargs
将文件名与其前面的印记分开:
#!/usr/bin/env bash
# This requires -printf, a GNU find extension
find . -iname '*.txt' -printf '--file=%p\0' | xargs -0 python myscript.py
...或者,更便携(在 MacOS 上运行,尽管仍然需要一个可以处理 NUL 分隔读取的 shell(例如 bash)):
#!/usr/bin/env bash
# requires find -print0 and xargs -0; these extensions are available on BSD as well as GNU
find . -iname '*.txt' -print0 |
while IFS= read -r -d '' f; do printf '--file=%s\0' "$f"; done |
xargs -0 python myscript.py
【讨论】:
【参考方案2】:您的标题似乎暗示您可以修改脚本。在这种情况下,请使用nargs
(参数数量)选项为-f
标志提供更多参数:
parser = argparse.ArgumentParser()
parser.add_argument('--files', '-f', nargs='+')
args = parser.parse_args()
print(args.files)
然后你就可以轻松使用你的 find 命令了:
15:44 $ find . -depth 1 | xargs python args.py -f
['./args.py', './for_clint', './install.sh', './sys_user.json']
否则,如果您无法修改脚本,请参阅@CharlesDuffy 的回答。
【讨论】:
你不能以这种方式安全地使用xargs
——如果你的参数多于单个命令行的容量,你不知道它是在文件名之后还是在-f
。 (此外,包含空格、文字引号、文字反斜杠等的文件名是不安全的)。
@CharlesDuffy 是的,我刚刚意识到这一点。认为我应该用这些警告编辑它或删除第二部分?
就个人而言,如果有安全的替代方案,我不会展示不安全的做法。以上是关于如何根据 shell 查找结果添加 argparse 标志的主要内容,如果未能解决你的问题,请参考以下文章