我尝试了以下命令,但无法解释结果:
ls **
我不确定它到底在输出什么以及为什么。
您很可能会看到一些 shell 的特殊功能,它允许通配符文件名模式跨目录边界匹配,而不是单个*
,它是仅在目录内匹配的通配符。
如果您没有这样的外壳,**
则可能等同于*
,因为“匹配零个或多个字符后跟零个或多个字符”与仅“匹配零个或多个字符”相同。
但是如果你确实有这样的外壳, **
将匹配当前目录和子目录中的所有文件和目录,而*
只匹配当前目录中的文件和目录。(在这两种情况下,名称以 开头的“点文件”.
都不匹配)。
**
当你以更具体的模式使用它时,它的真正威力就来了。例如,您可以指定所有.txt
文件,无论它们位于哪个子目录中**/*.txt
,而*.txt
仅匹配当前目录中的文件。
您应该查看您的 shell 的通配符匹配规则,以确定您的 shell 正在做什么。例如,bash
手册说:
*
匹配任何字符串,包括空字符串。当启用 'globstar' shell 选项并在文件名扩展上下文中使用 '*' 时,用作单个模式的两个相邻的 '*' 将匹配所有文件以及零个或多个目录和子目录。如果后跟“/”,则两个相邻的“*”将仅匹配目录和子目录。
在最近的版本中bash
,'globstar' shell 选项默认是禁用的。通过以下方式启用:
shopt -s globstar
我相信 zsh 也支持这种语法。
重要的是要记住通配符是由 shell 扩展的,而不是由ls
命令扩展的。如果键入ls **
, 或ls *.txt
,ls
命令本身永远不会看到*
字符;它只会看到与模式匹配的文件的扩展列表,就像您在命令行上键入了整个列表一样。
通过使用双星号 ( **
),您正在使用glob列出文件系统上的文件。glob 是用于匹配文件路径的文字或通配符字符串。使用一个或多个 glob 在文件系统上定位文件称为globbing。
除了 Linux shell,globbing 还用于各种配置文件中,以指定要定位的文件列表。例如:文件中要忽略的文件和文件夹.gitignore
,files
以及Typescript 项目include
中文件中的选项等。tsconfig.json
以下是通配符的一些最重要的方面,双星号 ( **
) 就是其中之一:
/
)分隔符始终是/
字符。段是两个分隔符之间的所有内容。
例子:Tests/HelloWorld.js
这里,Tests
和HelloWorld.js
是段,/
是分隔符。
*
)单个星号 ( ) 匹配一个段*
中的零个或多个字符。它用于对一个目录中的文件进行通配。
例子:*.js
此 glob 将匹配文件,HelloWorld.js
但不匹配文件,如Tests/HelloWorld.js
或Tests/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.js
或tests/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
目录中排除所有文件和文件夹。
而已!希望有帮助!
尽管其他一个或多个答案可能是正确的,但它们有点难以理解,尤其是如果您是像我这样的视觉型人。
所以我决定提供一个视觉答案,通过测试完全确认。
我创建了以下目录结构,每个级别都有两个文件“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
。
其他答案已很好地涵盖了此特定通配符的确切行为,但有关一般情况的信息可能很有用。
这种行为不限于ls
,并且被称为“globbing”,它是基于与现有文件名匹配的模式扩展。需要注意的是,这些模式不使用正则表达式语法。
Shell 在将参数发送到程序之前对其进行预处理。通常有多个级别的扩展,其中一些涉及 globbing。
有关文件 glob 模式中可用的其他通配符的更多信息的一个很好的资源是 unix 联机帮助页。可以在此处找到 glob 的在线版本。
最后,一个简单的例子说明这可以为您做什么,尤其是与其他 shell 扩展好东西结合使用时,在本例中是由bash
shell 提供的那些。有关此示例中使用的扩展的信息可以在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
等结合使用时的实用程序。