我尝试了以下命令,但我不明白结果:
ls **
**是什么意思? 我应该如何使用它?
**
您很可能会看到一些 shell 的特殊特性,它们允许通配符文件名模式跨目录边界进行匹配,这与单个 *相反,后者是仅在目录中匹配的通配符。
*
如果您没有这样的 shell,那么 **可能等同于 *,因为“匹配零个或多个字符后跟零个或多个字符”与“匹配零个或多个字符”相同。
但是,如果你有这样一个 shell, **将匹配工作目录 和子目录中的所有文件和目录,而 *只匹配工作目录中的文件和目录。(在这两种情况下,名称以 .开头的“点文件”都不匹配)。
.
**的真正威力来自于你在更具体的模式中使用它。例如,你可以用 **/*.txt指定所有的 .txt文件,不管它们在哪个子目录中,而 *.txt只匹配工作目录中的那些文件。
**/*.txt
.txt
*.txt
您应该查看 shell 的通配符匹配规则,以确定 shell 在做什么。例如,bash手册表示:
bash
* 匹配任何字符串,包括空字符串 启用“ globstar”shell 选项,并在文件名中使用“ *” 扩展上下文中,两个相邻的“ *”被用作一个单独的模式 匹配所有文件和零个或多个目录及子目录。 如果后面跟着一个’/’,两个相邻的’* 将只匹配 目录和子目录。
在 bash的最新版本中,默认情况下“ globstar”shell 选项是禁用的。通过以下方式启用:
shopt -s globstar
我相信 zsh 也支持这种语法。
请记住,通配符是由 shell 展开的,而不是由 ls命令展开的,这一点很重要。如果键入 ls **或 ls *.txt,则 ls命令本身不会看到 *字符; 它只会看到与模式匹配的扩展文件列表,就像您在命令行中键入了整个列表一样。
ls
ls *.txt
这个特定通配符的确切行为已经被其他答案很好地覆盖了,但是关于一般情况的信息可能是有用的。
这种行为不限于 ls,称为“ globbing”,它是基于与现有文件名匹配的模式的扩展。需要注意的是,这些模式并不使用正则表达式语法。
Shell 在将参数发送到程序之前对它们进行预处理。一般来说,膨胀有多个层次,其中一些涉及到球状膨胀。
有关在一个文件通配符模式中可用的其他通配符的更多信息,一个很好的资源是 unix manpage。可以找到 globb 的在线版本 给你。
最后,举一个简单的例子,说明这样做可以为您做些什么,特别是当与其他 shell 扩展好处(在本例中是由 bash shell 提供的好处)组合在一起时。关于这个例子中使用的扩展的信息可以在 初学者指南中找到——这是我的 goto 资源,尽管标题是这样的。
ls *{01..04}.{txt,csv}变成 ls *01.txt *01.csv *02.txt *02.csv *03.txt *03.csv *04.txt *04.csv
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等耦合时的实用程序。
mv
cp
rsync
通过使用双星号(**) ,可以使用 一团列出文件系统上的文件。通配符是用于匹配文件路径的字符串或通配符。使用一个或多个 globs 定位文件系统上的文件称为 球状的。
除了 Linux shell 之外,globbing 还用于各种配置文件,以指定要查找的文件列表。例如: 在 .gitignore文件中忽略的文件和文件夹,在打字工程中的 tsconfig.json文件中的 files和 include选项等。
.gitignore
tsconfig.json
files
include
以下是一些最重要的方面的球状和双星号(**)是其中之一:
/
分隔符总是 /字符。段是两个分隔符之间的所有内容。
例子: Tests/HelloWorld.js
Tests/HelloWorld.js
在这里,Tests和 HelloWorld.js是片段,/是分离器。
Tests
HelloWorld.js
单星号(*)匹配 一段中的零个或多个字符。它用于对一个目录中的文件进行全球化。
例子: *.js
*.js
这个 Globb 将匹配诸如 HelloWorld.js之类的文件,但不匹配诸如 Tests/HelloWorld.js或 Tests/UI/HelloWorld.js之类的文件
Tests/UI/HelloWorld.js
双星号(**)匹配整个 多个段中的零个或多个字符。它用于对嵌套目录中的文件进行 globbing。
例子: Tests/**/*.js
Tests/**/*.js
在这里,文件选择将仅限于 Tests目录。这个通配符将匹配诸如 Tests/HelloWorld.js、 Tests/UI/HelloWorld.js、 Tests/UI/Feature1/HelloWorld.js之类的文件。
Tests/UI/Feature1/HelloWorld.js
?
问号(?)匹配一个段中的单个字符。当某些文件或目录的名称只有一个字符不同时,可以使用 ?。
例子: tests/?at.js
tests/?at.js
这将匹配文件,如 tests/cat.js,test/Cat.js,test/bat.js等。
tests/cat.js
test/Cat.js
test/bat.js
[abc]
方括号([...])用方括号中提到的单个字符填充文件。
[...]
例子: tests/[CB]at.js
tests/[CB]at.js
这个地球仪将匹配文件,如 tests/Cat.js或 tests/Bat.js
tests/Cat.js
tests/Bat.js
[a-z]
方括号范围([a-z]) ,匹配范围中指定的一个字符。
例子: tests/feature[1-9]/HelloWorld.js
tests/feature[1-9]/HelloWorld.js
这个地球仪将匹配文件,如 tests/feature1/HelloWorld.js,test/feature2/HelloWorld.js等等... 到 9。
tests/feature1/HelloWorld.js
test/feature2/HelloWorld.js
9
!
否定(!)可用于排除某些文件。
例子1: tests/[!C]at.js
tests/[!C]at.js
这将排除文件 tests/Cat.js,并将匹配文件,如 tests/Bat.js,tests/bat.js,tests/cat.js。
tests/bat.js
在数组内的配置文件中也使用否定来否定或排除某些文件。
例子2: ['Tests/**/*.js', '!Tests/UI/**']
['Tests/**/*.js', '!Tests/UI/**']
这将排除 Tests/UI目录中的所有文件和文件夹。
Tests/UI
就是这样,希望能有帮助!
其他的答案是 很难做到这一点为视觉的人喜欢我。这里是一个插图 经测试完全确认。它显示了在阅读文本定义时不明显的 **的细微差别。
下面所示的目录结构具有以下属性:
f
o
我对照这个结构测试了下面表格标题中的所有模式, 在启用 globstar 的 Bash 中使用以下命令: stat -f "%N" <pattern>。
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
*/
**/
*/*.md
**/*.md
*/o/*
**/o/*
**/o/**
f.js
f.md
x
x/f.js
x/f.md
x/o
x/o/f.js
x/o/f.md
x/o/z
x/o/z/f.js
x/o/z/f.md
x/y
x/y/f.js
x/y/f.md
x/y/o
x/y/o/f.js
x/y/o/f.md
在这里,我们有选择地瞄准目录树中不同部分的 Markdown 文件:
*.md
x/o/**/*.md
**/o/**/*.md
**/o/*.md
**.md
**.md的工作原理与 *.md相似,而与 **/*.md不同。如果你给 **附加或者预先设置了 /以外的东西,它的工作原理和 *完全一样。