如何根据 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 标志的主要内容,如果未能解决你的问题,请参考以下文章

在 python 中调试 argpars

python argpare 模块的简单用法

如何在 shell 脚本中增加版本号?

shell脚本中如何编写程序med.sh,根据free命令的结果计算内存占有率

shell 往一个文件中添加内容

bash shell如何获取到命令执行结果的值?