繁体   English   中英

在 UNIX 环境中运行时,防止在未引用的 python 脚本参数中扩展通配符

[英]Prevent expansion of wildcards in non-quoted python script argument when running in UNIX environment

我有一个 python 脚本,我想为它提供一个包含通配符的参数(通常),指的是我想要处理的一系列文件。 这里的例子:

#!/usr/bin/env python

import argparse
import glob 

parser = argparse.ArgumentParser()
parser.add_argument('-i', action="store", dest="i")
results = parser.parse_args()
print 'argument i is: ', results.i
list_of_matched_files = glob.glob(results.i)

在这种情况下,如果用户像这样为传递的参数添加引号,一切都会很好:

./test_script.py -i "foo*.txt"

...但通常用户会忘记在参数中添加引号,并且当列表仅包含第一个匹配项时会被难住,因为 UNIX 已经扩展了列表并且 argparse 然后才获取第一个列表元素。

有没有办法(在脚本中)防止 UNIX 在将列表传递给 python 之前扩展它? 或者甚至只是为了测试参数是否不包含引号然后警告用户?

不。在脚本运行之前,shell(Bash、zsh、csh、fish 等等)会扩展通配符,并且脚本无法对它们做任何事情。 测试参数是否包含引号也不起作用,因为在将参数传递给脚本之前,shell 类似地从"foo*.txt"除了引号,所以 Python 看到的只是foo*.txt

进行扩展的不是 UNIX,而是 shell。

Bash 有一个选项set -o noglob (或-f )可以关闭通配符(文件名扩展),但这是非标准的。

如果您让最终用户访问命令行,那么他们真的应该了解引用。 例如,常用的find命令有一个-name参数,它可以采用 glob 结构,但必须以类似的方式引用它们。 您的程序与其他程序没有什么不同。

如果用户无法处理,那么也许你应该给他们一个不同的界面。 您可以极端地编写 GUI 或 Web/HTML 前端,但这可能太过分了。

或者为什么不提示输入文件名模式? 例如,您可以使用-p选项来指示提示,例如:

import argparse
import glob

parser = argparse.ArgumentParser()
parser.add_argument('-i', action="store", dest="i")
parser.add_argument('-p', action="store_true", default=False)

results = parser.parse_args()

if results.p:
    pattern = raw_input("Enter filename pattern: ")
else:
    pattern = results.i

list_of_matched_files = glob.glob(pattern)
print list_of_matched_files

(由于您的print语句,我假设了 Python 2)

这里的输入不是由 shell 读取的,而是由 python 读取的,除非你要求,否则它不会扩展 glob 结构。

可以从命令行使用set -f禁用扩展。 (使用set +f重新启用)。

正如 jwodder 正确地说的那样,这发生在脚本运行之前,所以我能想到的唯一方法是用一个 shell 脚本来包装它,该脚本暂时禁用扩展,运行 python 脚本,然后重新启用扩展。 在将列表传递给 python 之前阻止 UNIX 扩展列表是不可能的。

这是 Bash shell 的示例,显示了 @Tom Wyllie 所谈论的内容:

 alias sea='set -f; search_function' 
 search_function() { perl /home/scripts/search.pl $@ ; set +f; } 

这定义了一个名为“sea”的别名:

  1. 关闭扩展(“set -f”)
  2. 运行作为 perl 脚本的 search_function 函数
  3. 重新打开扩展(“set +f”)

这样做的问题是,如果用户使用 ^C 或类似的命令停止执行,则扩展可能不会重新打开,让用户感到困惑,为什么“ls *”不起作用。 所以我不一定提倡使用它。 :)。

这对我有用:

files = sys.argv[1:]

即使命令行上只有一个字符串,shell 也会扩展通配符并用列表填充 sys.argv[]。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM