119

我尝试了以下命令,但无法解释结果:

ls **

我不确定它到底在输出什么以及为什么。

4

4 回答 4

202

您很可能会看到一些 shell 的特殊功能,它允许通配符文件名模式跨目录边界匹配,而不是单个*,它是仅在目录内匹配的通配符。

如果您没有这样的外壳,**则可能等同于*,因为“匹配零个或多个字符后跟零个或多个字符”与仅“匹配零个或多个字符”相同。

但是如果你确实有这样的外壳, **将匹配当前目录和子目录中的所有文件和目录,而*只匹配当前目录中的文件和目录。(在这两种情况下,名称以 开头的“点文件”.都不匹配)。

**当你以更具体的模式使用它时,它的真正威力就来了。例如,您可以指定所有.txt文件,无论它们位于哪个子目录中**/*.txt,而*.txt仅匹配当前目录中的文件。

您应该查看您的 shell 的通配符匹配规则,以确定您的 shell 正在做什么。例如,bash手册说:

*
匹配任何字符串,包括空字符串。当启用 'globstar' shell 选项并在文件名扩展上下文中使用 '*' 时,用作单个模式的两个相邻的 '*' 将匹配所有文件以及零个或多个目录和子目录。如果后跟“/”,则两个相邻的“*”将仅匹配目录和子目录。

在最近的版本中bash,'globstar' shell 选项默认是禁用的。通过以下方式启用:

shopt -s globstar

我相信 zsh 也支持这种语法。

重要的是要记住通配符是由 shell 扩展的,而不是由ls命令扩展的。如果键入ls **, 或ls *.txtls命令本身永远不会看到*字符;它只会看到与模式匹配的文件的扩展列表,就像您在命令行上键入了整个列表一样。

于 2015-01-28T18:24:10.833 回答
96

通配符

通过使用双星号 ( **),您正在使用glob列出文件系统上的文件。glob 是用于匹配文件路径的文字或通配符字符串。使用一个或多个 glob 在文件系统上定位文件称为globbing

除了 Linux shell,globbing 还用于各种配置文件中,以指定要定位的文件列表。例如:文件中要忽略的文件和文件夹.gitignorefiles以及Typescript 项目include中文件中的选项等。tsconfig.json

以下是通配符的一些最重要的方面,双星号 ( **) 就是其中之一:


段和分隔符 ( /)

分隔符始终是/字符。段是两个分隔符之间的所有内容。

例子:Tests/HelloWorld.js

这里,TestsHelloWorld.js是段,/是分隔符。


单个星号 ( *)

单个星号 ( ) 匹配一个*中的零个或多个字符。它用于对一个目录中的文件进行通配。

例子:*.js

此 glob 将匹配文件,HelloWorld.js但不匹配文件,如Tests/HelloWorld.jsTests/UI/HelloWorld.js


双星号 ( **)

双星号 ( ) 匹配多个段中的**零个或多个字符。它用于对嵌套目录中的文件进行通配。

例子:Tests/**/*.js

在这里,文件选择将被限制在Tests目录中。glob 将匹配文件,例如Tests/HelloWorld.js, Tests/UI/HelloWorld.js, Tests/UI/Feature1/HelloWorld.js.


问号( ?)

问号( ?) 匹配一个段中的单个字符。当某些文件或目录的名称仅相差一个字符时,您可以使用?.

例子:tests/?at.js

这将匹配诸如tests/cat.js,test/Cat.js等文件test/bat.js


方括号 ( [abc])

方括号 ( [...]) 使用方括号中提到的单个字符对文件进行通配。

例子:tests/[CB]at.js

这个 glob 将匹配文件,如tests/Cat.jstests/Bat.js


方括号范围 ( [a-z])

方括号范围 ( [a-z]),匹配范围中指定的一个字符。

例子:tests/feature[1-9]/HelloWorld.js

这个 glob 将匹配文件,如tests/feature1/HelloWorld.js,test/feature2/HelloWorld.js等等... upto 9.


否定 ( !)

否定 (!) 可用于排除某些文件。

示例 1:tests/[!C]at.js

这将排除文件tests/Cat.js并匹配文件,如tests/Bat.js, tests/bat.js, tests/cat.js.

否定也用于数组内的配置文件中以否定或排除某些文件。

示例 2:['Tests/**/*.js', '!Tests/UI/**']

这将从Tests/UI目录中排除所有文件和文件夹。


而已!希望有帮助!

于 2020-07-19T20:51:31.767 回答
22

尽管其他一个或多个答案可能是正确的,但它们有点难以理解,尤其是如果您是像我这样的视觉型人。

所以我决定提供一个视觉答案,通过测试完全确认

我创建了以下目录结构,每个级别都有两个文件“f”,一个有文件扩展名,一个没有文件扩展名,然后在启用 globstar 的达尔文 Bash 中使用以下命令测试下表标题中的所有模式:stat -f "%N" <pattern>.

如果您是一个视觉型的人,那么查看表格会让您更深入地了解含义**而不仅仅是阅读其他好答案中的定义。

.
├── f
├── f.md
└── x
    ├── f
    ├── f.md
    └── y
        ├── f
        ├── f.md
        └── z
            ├── f
            └── f.md

比较*_**

* ** */ **/ **/*.* x/*.*
或者
*/*.*
x/*
或者
*/*
x/**
或者
*/**
f ✅</td> ✅</td>
f.md ✅</td> ✅</td> ✅</td>
x ✅</td> ✅</td> ✅</td> ✅</td> ✅</td>
x/f ✅</td> ✅</td> ✅</td>
x/f.md ✅</td> ✅</td> ✅</td> ✅</td> ✅</td>
x/y ✅</td> ✅</td> ✅</td> ✅</td>
x/y/f ✅</td> ✅</td>
x/y/f.md ✅</td> ✅</td> ✅</td>
x/y/z ✅</td> ✅</td> ✅</td>
x/y/z/f ✅</td> ✅</td>
x/y/z/f.md ✅</td> ✅</td> ✅</td>

在树中匹配或查找文件

*.md


**.md
**f.md
f**.md
*/*.md
x/*.md
**/x/*.md



*/*/*.md
x/*/*.md
**/y/*.md



*/*/*/*.md
x/*/*/*.md
**/z/*.md




x/**/*.md




**/*.md





f
f.md ✅</td> ✅</td>
x
x/f
x/f.md ✅</td> ✅</td> ✅</td>
x/y
x/y/f
x/y/f.md ✅</td> ✅</td> ✅</td>
x/y/z
x/y/z/f
x/y/z/f.md ✅</td> ✅</td> ✅</td>

请注意,在前面添加或附加**除 a 以外的任何内容/会导致其与 的行为相同*,如上所示**.md**f.md,例如,两者都不匹配x/y/f.md

于 2021-03-22T10:37:42.990 回答
10

其他答案已很好地涵盖了此特定通配符的确切行为,但有关一般情况的信息可能很有用。

这种行为不限于ls,并且被称为“globbing”,它是基于与现有文件名匹配的模式扩展。需要注意的是,这些模式不使用正则表达式语法。

Shell 在将参数发送到程序之前对其进行预处理。通常有多个级别的扩展,其中一些涉及 globbing。

有关文件 glob 模式中可用的其他通配符的更多信息的一个很好的资源是 unix 联机帮助页。可以在此处找到 glob 的在线版本。

最后,一个简单的例子说明这可以为您做什么,尤其是与其他 shell 扩展好东西结合使用时,在本例中是由bashshell 提供的那些。有关此示例中使用的扩展的信息可以在Bash Guide for Beginners中找到- 这是我的 goto 资源,尽管有标题。

ls *{01..04}.{txt,csv}变成ls *01.txt *01.csv *02.txt *02.csv *03.txt *03.csv *04.txt *04.csv

可以输出如下内容:

input_01.txt input_02.txt input_03.txt input_04.txt output_01.csv output_02.csv output_03.csv output_04.csv

跳过这些:

input_05.txt input_06.txt input_07.txt input_08.txt input_09.txt input_10.txt output_05.csv output_06.csv output_07.csv output_08.csv output_09.csv output_10.csv

一个简单的例子,但是如果您知道此行为不是特定于 的ls,那么您可以想象与mv, cp,rsync等结合使用时的实用程序。

于 2015-01-28T18:38:46.007 回答