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

在UNIX环境中运行时,防止在非引号的python脚本参数中扩展通配符,python,unix,argparse,Python,Unix,Argparse,我有一个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: ', re

我有一个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

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


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

进行扩展的不是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读取的,除非您要求,否则python不会扩展glob构造。

下面是Bash shell的一个示例,展示了@Tom Wyllie所说的内容:

 alias sea='set -f; search_function' 
 search_function() { perl /home/scripts/search.pl $@ ; set +f; } 
这定义了一个名为“sea”的别名:

  • 关闭扩展(“设置-f”)
  • 运行search_函数,它是一个perl脚本
  • 重新打开扩展(“设置+f”)
  • 这样做的问题是,如果用户停止执行^C或类似的命令,那么扩展可能不会重新启动,用户会感到困惑,为什么“ls*”不起作用。所以我不一定主张使用这个

    这对我很有用:

    files = sys.argv[1:]
    

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

    查看
    sys..argv
    以查看
    argparse
    从shell中获得了什么。