用glob参数递归匹配文件名

| 我一直在尝试使用
glob.glob
os.walk
递归获取命令行参数(
sys.argv[1]
)中与全局模式匹配的文件的列表。问题是,bash(以及其他许多shell)会自动将glob模式扩展为文件名。 那么标准的UNIX程序(例如
grep -R
)如何做到这一点?我意识到它们不在python中,但是如果这是在shell级别发生的,那应该没关系,对吧?脚本是否有办法告诉外壳程序不要自动扩展glob模式?看来ѭ4会禁用通配符,但是我不确定如何足够早地运行它。 我已经看过使用Glob()在Python中递归查找文件吗?但是,这实际上并不涵盖从命令行参数获取glob模式。 谢谢! 编辑: 类似于grep的perl脚本ack接受perl regex作为其参数之一。这样,
ack .*
打印出每个文件的每一行。但是ѭ6应该扩展到目录中的所有隐藏文件。我尝试阅读脚本,但我不了解perl;怎么做呢?     
已邀请:
Shell甚至在考虑调用命令之前就执行了全局扩展。诸如grep之类的程序不会做任何事情来防止阻塞:它们不能。作为这些程序的调用者,您必须告诉Shell您要将特殊字符(例如
*
?
)传递给程序,而不要让Shell解释它们。您可以通过将其放在引号中来实现:
grep -E \'ba(na)* split\' *.txt
(在名为
.txt
的所有文件中查找
ba split
bana split
等)。在这种情况下,单引号或双引号都可以解决问题。在单引号之间,shell不会扩展任何内容。在双引号之间,仍会解释
$
`
和ѭ15.。您还可以通过在单个字符前面加反斜杠来防止单个字符受shell扩展的影响。不仅需要保护通配符,而且还需要保护通配符。例如,在上面,模式中的空格用引号引起来,因此它是
grep
参数的一部分,而不是参数分隔符。编写以上代码段的替代方法包括
grep -E \"ba(na)* split\" *.txt
grep -E ba\\(na\\)\\*\\ split *.txt
对于大多数Shell,如果参数包含通配符,但是模式与任何文件都不匹配,则模式将保持不变并传递给基础命令。所以像这样的命令
grep b[an]*a *.txt
根据系统上存在哪些文件,其效果会有所不同。如果当前目录不包含任何名称以ѭ19开头的文件,该命令将在名称与ѭ21匹配的文件中搜索模式
b[an]*a
。如果当前目录包含名为
baclava
bnm
hello.txt
的文件,该命令将扩展为
grep baclava bnm hello.txt
,因此它将在两个文件
bnm
hello.txt
中搜索模式
baclava
。不用说,在脚本中依靠它是一个坏主意。在命令行上,它有时可以保存键入内容,但这很冒险。 在不包含点文件的目录中运行
ack .*
时,外壳程序将运行
ack . ..
。然后,
ack
命令的行为是递归地打印ѭ33under(当前目录的父目录)下所有文件中的所有非空行(模式
.
:匹配任意一个字符)。与
ack \'.*\'
相反,后者在当前目录及其子目录中搜索模式
.*
(匹配任何内容)(由于不传递任何文件名参数时
ack
的行为)。     
谈到grep时,它只接受文件名列表,而不会自己进行glob扩展。如果确实需要将模式作为参数传递,则必须在命令行上用单引号将其引起来。但是在执行此操作之前,请考虑让外壳执行其专为它设计的工作。     
是的,
set -f
,您的位置正确。 听起来您将要从shell调用python程序。 每当您使用Shell发出命令时,它都会尝试扫描cmd行并处理通配符,命令替换以及其他所有内容。 因此,在命令行上运行程序之前,必须关闭全局
set -f
echo *
*

myprogram *.txt
会将字符串\'*。txt \'传递给您的程序。然后,您可以使用内部glob来获取文件。 或者,您可以通过创建包装器脚本来执行基本相同的操作
 #!/bin/bash
 set -f
 myProgram ${@}
其中,
${@} are the arguments you pass in when you start
myProgram`来自命令行,crontab或来自另一个进程的exec(...)。 我希望这有帮助。     

要回复问题请先登录注册