我知道**/*.ext
扩展到与*.ext
匹配的所有子目录中的所有文件,但是什么是类似的扩展,包括当前目录中的所有此类文件?< / p>
答案 0 :(得分:99)
这将适用于Bash 4:
ls -l {,**/}*.ext
为了使双星号glob工作,需要设置globstar
选项(默认值:on):
shopt -s globstar
来自man bash
:
globstar If set, the pattern ** used in a filename expansion con‐ text will match a files and zero or more directories and subdirectories. If the pattern is followed by a /, only directories and subdirectories match.
现在我想知道是否曾经有过globstar处理中的错误,因为现在只使用ls **/*.ext
我得到了正确的结果。
无论如何,我查看了使用VLC存储库的analysis kenorb,并发现了该分析的一些问题以及我上面的答案:
与find
命令输出的比较无效,因为指定-type f
不包括其他文件类型(特别是目录),并且列出的ls
命令可能会这样做。此外,列出的其中一个命令ls -1 {,**/}*.*
- 似乎基于我的上面的命令,只输出包含点的名称,用于子目录中的那些文件。 OP的问题和我的答案包括一个点,因为正在寻找的是具有特定扩展名的文件。
然而,最重要的是,使用带有globstar模式ls
的{{1}}命令存在一个特殊问题。由于模式被Bash扩展到正在检查的树中的所有文件名(和目录名),因此出现了许多重复项。扩展后,**
命令会列出 每个 及其内容(如果它们是目录)。
示例:
在我们当前的目录中是子目录ls
及其内容:
A
在该树中,A
└── AB
└── ABC
├── ABC1
├── ABC2
└── ABCD
└── ABCD1
扩展为“AA / AB A / AB / ABC A / AB / ABC / ABC1 A / AB / ABC / ABC2 A / AB / ABC / ABCD A / AB / ABC / ABCD / ABCD1“(7个条目)。如果你做**
那就是你得到的确切输出,并且每个条目都代表一次。 然而 ,如果您执行echo **
,则会输出这些条目的 每个 的列表。所以基本上它ls **
后跟ls A
等,所以ls A/AB
会显示两次。此外,A/AB
将分别设置每个子目录的输出:
ls
因此,使用...
<blank line>
directory name:
content-item
content-item
计算所有空白行和目录名称部分标题,这些标题会使计数更加突出。
这是你不应该parse ls
的另一个原因。
作为进一步分析的结果,我建议不要在任何情况下使用globstar模式,而不是以这种方式迭代文件树:
wc -l
作为最后的比较,我使用了一个方便的Bash源代码库,并且做了这个:
for entry in **
do
something "$entry"
done
我使用shopt -s globstar dotglob
diff <(echo ** | tr ' ' '\n') <(find . | sed 's|\./||' | sort)
0a1
> .
将空格更改为换行符,这仅在此处有效,因为没有名称包含空格。我使用tr
从sed
的每一行输出中删除了前导./
。我对find
的输出进行了排序,因为它通常是未排序的,并且Bash的globs扩展已经排序。如您所见,find
的唯一输出是diff
输出的当前目录.
。当我做find
时,输出的行几乎是两倍。
答案 1 :(得分:12)
这将打印当前目录及其子目录中以“.ext”结尾的所有文件。
find . -name '*.ext' -print
答案 2 :(得分:6)
您可以使用:**/*.*
递归包含所有文件(由shopt -s globstar
启用)。
请在下面查看其他变体的测试以及它们的行为方式。
在示例VLC存储库文件夹中测试包含3472个文件的文件夹:
(根据find . -type f | wc -l
计算的总文件数为3472)
ls -1 **/*.*
- 返回3338 ls -1 {,**/}*.*
- 返回3341(由Dennis提议)ls -1 {,**/}*
- 返回8265 ls -1 **/*
- 返回7817,隐藏文件除外(由Dennis提议)ls -1 **/{.[^.],}*
- 返回7869(由Dennis提议)ls -1 {,**/}.?*
- 返回15855 ls -1 {,**/}.*
- 返回20321 所以我认为递归列出所有文件的最接近的方法是gniourf-gniourf comment的第一个示例(**/*.*
)(假设文件具有适当的扩展名,或使用特定的扩展名),如第二个例子提供了更多重复项,如下所示:
$ diff -u <(ls -1 {,**/}*.*) <(ls -1 **/*.*)
--- /dev/fd/63 2015-04-19 15:25:07.000000000 +0100
+++ /dev/fd/62 2015-04-19 15:25:07.000000000 +0100
@@ -1,6 +1,4 @@
COPYING.LIB
-COPYING.LIB
-Makefile.am
Makefile.am
@@ -45,7 +43,6 @@
compat/tdestroy.c
compat/vasprintf.c
configure.ac
-configure.ac
,另一个产生更多重复。
要包含隐藏文件,请使用:shopt -s dotglob
(由shopt -u dotglob
禁用)。不建议这样做,因为它会影响mv
或rm
等命令,您可能会意外删除错误的文件。
答案 3 :(得分:3)
$ find . -type f
这将列出当前目录中的所有文件。然后,您可以使用-exec
对输出执行其他命令$find . -type f -exec grep "foo" {} \;
这将从查找字符串“foo”grep每个文件。
答案 4 :(得分:3)
为什么不使用大括号扩展来包含当前目录呢?
./{*,**/*}.ext
Brace扩展在全局扩展之前发生,因此您可以使用旧版本的bash有效地执行您想要的操作,并且可以在较新版本中放弃使用globstar进行修改。
此外,bash中的优秀做法是在您的glob模式中包含前导./
。