在 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
.
您可以从命令行使用set -f
禁用扩展。 (使用 set +f
重新启用)。
正如 jwodder 所说的那样,这发生在脚本 运行 之前,所以我能想到的唯一方法是用 shell 脚本包装它,暂时禁用扩展, 运行s python 脚本,并重新启用扩展。阻止 UNIX 在将列表传递给 python 之前扩展列表是不可能的。
不是 UNIX 在做扩展,是 shell。
Bash 有一个选项 set -o noglob
(或 -f
)可以关闭 globbing(文件名扩展),但这是非标准的。
如果您向最终用户授予命令行访问权限,那么他们真的应该了解引用。例如,常用的 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
(我假设 Python 2 因为你的 print
声明)
此处的输入不是由 shell 读取,而是由 python 读取,除非您要求,否则不会扩展 glob 结构。
这是 Bash shell 的示例,显示了@Tom Wyllie 所说的内容:
alias sea='set -f; search_function'
search_function() { perl /home/scripts/search.pl $@ ; set +f; }
这定义了一个名为 "sea" 的别名,它:
- 关闭扩展("set -f")
- 运行 search_function 函数,它是一个 perl 脚本
- 重新打开扩展("set +f")
问题在于,如果用户使用 ^C 或类似的命令停止执行,则扩展可能无法返回,让用户感到困惑,为什么 "ls *" 不起作用。所以我不一定提倡使用这个。 :).
这对我有用:
files = sys.argv[1:]
即使命令行上只有一个字符串,shell 也会扩展通配符并用列表填充 sys.argv[]。
我有一个 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
禁用扩展。 (使用 set +f
重新启用)。
正如 jwodder 所说的那样,这发生在脚本 运行 之前,所以我能想到的唯一方法是用 shell 脚本包装它,暂时禁用扩展, 运行s python 脚本,并重新启用扩展。阻止 UNIX 在将列表传递给 python 之前扩展列表是不可能的。
不是 UNIX 在做扩展,是 shell。
Bash 有一个选项 set -o noglob
(或 -f
)可以关闭 globbing(文件名扩展),但这是非标准的。
如果您向最终用户授予命令行访问权限,那么他们真的应该了解引用。例如,常用的 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
(我假设 Python 2 因为你的 print
声明)
此处的输入不是由 shell 读取,而是由 python 读取,除非您要求,否则不会扩展 glob 结构。
这是 Bash shell 的示例,显示了@Tom Wyllie 所说的内容:
alias sea='set -f; search_function'
search_function() { perl /home/scripts/search.pl $@ ; set +f; }
这定义了一个名为 "sea" 的别名,它:
- 关闭扩展("set -f")
- 运行 search_function 函数,它是一个 perl 脚本
- 重新打开扩展("set +f")
问题在于,如果用户使用 ^C 或类似的命令停止执行,则扩展可能无法返回,让用户感到困惑,为什么 "ls *" 不起作用。所以我不一定提倡使用这个。 :).
这对我有用:
files = sys.argv[1:]
即使命令行上只有一个字符串,shell 也会扩展通配符并用列表填充 sys.argv[]。