我尝试了以下命令,但无法解释结果:
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.mdf**.md |
*/*.mdx/*.md**/x/*.md |
*/*/*.mdx/*/*.md**/y/*.md |
*/*/*/*.mdx/*/*/*.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 扩展好东西结合使用时,在本例中是由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等结合使用时的实用程序。