递归全局?


80

我想写这样的东西:

$ ls **.py

为了获取所有.py文件名,请递归遍历目录层次结构。

即使找到.py文件,shell(bash)也会给出以下输出:

ls: cannot access **.py: No such file or directory

有什么办法可以做我想要的吗?

编辑:我想指定我对的特定情况不感兴趣ls,但问题是关于glob语法。

Answers:


98

为了在bash中执行递归glob,您需要globstarbash版本4或更高版本中的功能。

从bash手册页:

globstar
    If set, the pattern ** used in a pathname expansion context will
    match all files and zero or more directories and subdirectories.
    If the pattern is followed by a /, only directories and
    subdirectories match.

对于您的示例模式:

shopt -s globstar
ls **/*.py

2
我建议您也启用nullglob
glenn jackman 2012年

6
@glennjackman但在启用之前nullglob,我强烈建议您阅读以下警告
Serge Stroobandt

2
^警告已经移到这里
usandfriends 15/11/29

1
使用bash 3.2,wc -l {**,.}/*.py效果很好
Raphael

@Raphael我仔细检查了发行说明,它肯定说它是在4.0中引入的。也许您的发行版已经为此移植了补丁?IIRC RHEL 5已向后移植了一些功能。还值得注意的是,

10
find . -name '*.py'

**除了做一个*以外,不做其他任何事情,它们都在当前目录中运行


有趣。但是,我更专注于glob语法,因为我必须在配置文件(include指令)中使用它。我不需要文件列表。
Paolo 2012年

2
@Doug O'Neal,这不再是事实。庆典已经复制了zsh的功能(尽管它采用了语法更接近ksh93的和类似的ksh,不支持的zsh的通配符预选赛又限制了它的实用性)
斯特凡Chazelas

find如果没有bash 4,可以做很多事情。示例:(yourcommand `find . -name '*.py'`注意反引号);find . -name '*.py' -exec yourcommand {} \;
火星

5

自Bash 4(还包括zsh)以来,添加了新的globlob选项globstar),该选项**在设置模式时将以不同的方式处理。

它匹配通配符模式,并返回匹配的文件和目录名称,然后通过用匹配的项替换命令中的通配符模式。

通常,当您使用时**,它的工作方式类似于*,但是它以递归方式递归所有目录(如循环)。

要查看是否已启用,请通过shopt globstar(在脚本中使用shopt -q globstar)进行检查。

该示例**.py仅适用于当前目录,因为它不会返回可以递归的目录列表,因此这就是为什么您需要使用多个目录级通配符的原因**/*.py,因此更深入。

找到我为递归查找所有文件所做的少量语法测试。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.