我已经尝试了以下命令,但我无法解释结果:
ls **
我不确定它输出的是什么以及为什么。

您很可能会看到一些 shell 的特殊功能,它允许通配符文件名模式跨目录边界进行匹配,而不是单个*
,后者是仅在目录内匹配的通配符。
如果您没有这样的 shell,**
可能等同于*
,因为“匹配零个或多个字符后跟零个或多个字符”与“匹配零个或多个字符”相同。
但是,如果你有这样一个 shell,**
将匹配当前目录和子目录中的所有文件和目录,而*
只匹配当前目录中的文件和目录。
**
的真正力量来自于您在更具体的模式中使用它。例如,您可以使用**/*.txt
指定所有.txt
文件,而*.txt
仅匹配当前目录中的文件。
您应该查看您的 shell 的通配符匹配规则,以确定您的 shell 正在做什么。例如,bash
manual说:
*
匹配任何字符串,包括空字符串。当启用“globstar”shell 选项并且在文件名扩展上下文中使用“*”时,用作单个模式的两个相邻的“*”将匹配所有文件以及零个或多个目录和子目录。如果后跟“/”,则两个相邻的“*”将仅匹配目录和子目录。
在bash
的最新版本中,默认情况下禁用“globstar”shell 选项。通过以下方式启用:
shopt -s globstar
我相信 zsh 也支持这种语法。
重要的是要记住,通配符是由 shell 扩展的,而不是由ls
命令扩展的。如果键入ls **
或ls *.txt
,则ls
命令本身不会看到*
字符;它只会看到与该模式匹配的文件的扩展列表,就像在命令行上键入整个列表一样。

滚球
通过使用双星号 (**
),您可以使用glob来列出文件系统上的文件。glob 是用于匹配文件路径的文字或通配符字符串。使用一个或多个 glob 来定位文件系统上的文件称为globing。
除 Linux shell 外,globbing 还用于各种配置文件中,以指定要定位的文件列表。例如:Typescript 项目中.gitignore
文件中的要忽略的文件和文件夹、tsconfig.json
文件中的files
和include
选项等。
以下是 globbing 的一些最重要的方面,双星(**
)是其中之一:
段和分隔符 (/
)
分隔符始终是/
字符。段是两个分隔符之间的所有内容。
Tests/HelloWorld.js
这里,Tests
和HelloWorld.js
是段,/
是分隔符。
单星号 (*
)
Single Asterisk (*
) 匹配一个段中的零个或多个字符。它用于在一个目录中全局化文件。
*.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
等文件...直到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
目录中的所有文件和文件夹。
就这样。希望有帮助!

对于视觉的人
其他答案是很难grok对于像我这样的视觉人。这里是一个插图通过测试完全确认。它显示了在阅读文本定义时不明显的**
的细微差别。
下面显示的目录结构具有以下属性:
四个目录级别(计算根)
两个文件f
在每个级别具有不同的文件扩展名
两个同名目录o
,位于不同深度的不同分支上
我在启用 globstar 的 Bash 中使用以下命令,针对此结构测试了下面表标题中的所有模式:stat -f "%N" <pattern>
。
.
├── f.js
├── f.md
└── x
├── f.js
├── f.md
├── o
│ ├── f.js
│ ├── f.md
│ └── z
│ ├── f.js
│ └── f.md
└── y
├── f.js
├── f.md
└── o
├── f.js
└── f.md
Comparing*
to**
选择性深度靶向
在这里,我们有选择地将 Markdown 文件定位在目录树的不同部分:
?**.md
is the same as*.md
**.md
的工作原理类似于*.md
,而不是**/*.md
。如果您在**
上附加或前置除/
以外的任何内容,则其工作原理与*
完全相同。
这个特定通配符的确切行为已经被其他答案很好地覆盖了,但是关于一般情况的信息可能是有用的。
此行为不限于ls
,并且被称为“globbing”,这是基于与现有文件名的匹配的模式的扩展。
shell 在将参数发送到程序之前对其进行预处理。通常有多个扩展级别,其中一些涉及 globbing。
有关文件 glob 模式中其他通配符的更多信息的一个很好的资源是 unix manpage。可以找到 glob 的在线版本here。
最后,这是一个简单的例子,它可以为您做什么,特别是与其他 shell 扩展功能结合使用时,在这种情况下,由bash
shell 提供。有关此示例中使用的扩展的信息可以在Bash Guide for Beginners中找到-这是我的 goto 资源,尽管标题。
ls *{01..04}.{txt,csv}
becomesls *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
等耦合时的实用程序。
本站系公益性非盈利分享网址,本文来自用户投稿,不代表码文网立场,如若转载,请注明出处
评论列表(24条)