Python 使用glob参数递归匹配文件名

Python 使用glob参数递归匹配文件名,python,bash,glob,argv,Python,Bash,Glob,Argv,我一直在尝试使用glob.glob和os.walk递归地在命令行参数(sys.argv[1])中获取与glob模式匹配的文件列表。问题是,bash(以及许多其他shell)自动将glob模式扩展为文件名 那么,标准unix程序(例如grep-R)是如何做到这一点的呢?我意识到它们不在python中,但如果这是在shell级别发生的,那应该没关系,对吧?脚本有没有办法告诉shell不要自动扩展glob模式?看起来set-f将禁用globbing,但可以这么说,我不确定如何尽早运行它 我已经看到了,

我一直在尝试使用
glob.glob
os.walk
递归地在命令行参数(
sys.argv[1]
)中获取与glob模式匹配的文件列表。问题是,bash(以及许多其他shell)自动将glob模式扩展为文件名

那么,标准unix程序(例如
grep-R
)是如何做到这一点的呢?我意识到它们不在python中,但如果这是在shell级别发生的,那应该没关系,对吧?脚本有没有办法告诉shell不要自动扩展glob模式?看起来
set-f
将禁用globbing,但可以这么说,我不确定如何尽早运行它

我已经看到了,但这并不包括从命令行参数中获取glob模式

谢谢

编辑:


类似grep的perl脚本接受perl正则表达式作为其参数之一。因此,
ack.*
打印出每个文件的每一行。但是
*
应该扩展到目录中的所有隐藏文件。我试着阅读脚本,但我不懂perl;它如何做到这一点呢?

当涉及到grep时,它只接受一个文件名列表,而不进行glob扩展本身。如果确实需要将模式作为参数传递,则必须在命令行中使用单引号将其引用。但是在你这样做之前,考虑让shell完成它设计的任务。

< P>是的,<代码> SET-F<代码>,你在正确的轨道上。

听起来像是要从shell调用python程序

每当您使用shell发出命令时,它都会尝试扫描cmd行并处理通配符、命令替换和一大堆其他内容

因此,在命令行上运行程序之前,您必须关闭全球化功能

set -f
echo *
*

myprogram *.txt
将字符串“*.txt”传递给您的程序。然后您可以使用内部globbing来获取文件

或者,您也可以通过创建包装器脚本来完成基本相同的工作

 #!/bin/bash
 set -f
 myProgram ${@}
其中,
${@}是从命令行、crontab或通过exec(…)从另一个进程启动
myProgram`时传入的参数


我希望这会有所帮助。

shell甚至在考虑调用命令之前就执行glob扩展。像grep这样的程序不会做任何事情来阻止globbing:它们不能。作为这些程序的调用者,您必须告诉shell您希望将特殊字符(如
*
传递给程序,而不是让shell解释它们。您可以将它们放在引号中:

grep -E 'ba(na)* split' *.txt
(在所有名为
.txt
的文件中查找
ba-split
bana-split
等)在这种情况下,单引号或双引号都可以。在单引号之间,shell不展开任何内容。在双引号之间,
$
`
\
仍然被解释。您还可以通过在单个字符前面加反斜杠来防止其外壳扩展。需要保护的不仅仅是通配符;例如,在上面,模式中的空格是引号,因此它是
grep
的参数的一部分,而不是参数分隔符。编写上述代码段的其他方法包括

grep -E "ba(na)* split" *.txt
grep -E ba\(na\)\*\ split *.txt
对于大多数shell,如果参数包含通配符,但模式与任何文件都不匹配,则模式保持不变并传递给基础命令。这样的命令

grep b[an]*a *.txt
具有不同的效果,具体取决于系统上存在哪些文件。如果当前目录不包含名称以
b
开头的任何文件,则命令将在名称与
*.txt
匹配的文件中搜索模式
b[an]*a
。如果当前目录包含名为
baclava
bnm
hello.txt
的文件,则命令将扩展到
grep baclava bnm hello.txt
,因此它将在两个文件
bnm
hello.txt
中搜索模式
baclava
。不用说,在脚本中依赖它是个坏主意;在命令行上,它有时可以保存键入,但这是有风险的


在不包含点文件的目录中运行
ack.*
时,shell将运行
ack。然后,
ack
命令的行为是递归地打印
(当前目录的父目录)下所有文件中的所有非空行(模式
:匹配任何一个字符)。与
ack.*.
相比,它在当前目录及其子目录中搜索模式
*
(匹配任何内容)(这是由于当您不传递任何文件名参数时
ack
的行为)。

啊,我明白了,这是一个很好的观点。多年来一直在使用grep,但从未注意到它实际上对glob-like模式没有任何作用(其他unix命令也是如此)。好吧,谢谢!这符合Unix的理念,即每个工具都应该有单独的责任。您的意思是首先在shell中显式运行run
set-f
,然后运行程序吗?我认为用bash脚本包装python程序,首先调用
set-f
是行不通的。。。好吧,谢谢!只是尝试了一下,唉,程序仍然得到了扩展的文件名。当我将
myProgram
替换为
echo${@}
时,也发生了同样的事情;它打印的是文件名,而不是glob.doah。是的,${@}将从cmd行,$1,$2获取参数$n、 这意味着这些值已经被扩展。因此,前面的注释(我现在看不到),您需要将参数封装在单引号中,即,
myWrapper…“*”。。。祝你好运请参阅我的编辑。那么,ack程序如何能够在没有引号或反斜杠的情况下接受perl正则表达式呢?@Bryan:事实并非如此,请更仔细地查看输出(或查看我的编辑)。