我已经尝试了以下命令,但我无法解释它:
ls **
但我不确定输出到底是什么以及为什么会这样。
答案 0 :(得分:107)
它可能使用某些shell的特殊功能,允许**
执行递归匹配,而不是单个*
,它只在当前目录中匹配。
通配符*
匹配当前目录中的任何文件或目录(其名称不以.
开头)。
根据您使用的是哪个shell以及使用哪些设置,**
可能等同于*
;它可以匹配零个或多个字符后跟零个或多个字符,这与仅匹配零个或多个字符相同。
但是对于一些shell,通过一些设置,**
是*
的递归版本,匹配当前目录和子目录中的所有文件和目录。
引用bash
manual:
'*'
匹配任何字符串,包括空字符串。当。。。的时候 启用`globstar'hell选项,文件名中使用`*' 扩展上下文,两个相邻的`*'用作单个模式 匹配所有文件和零个或多个目录和子目录。 如果后跟一个“/”,则两个相邻的“*”仅匹配 目录和子目录。
仅当globstar
选项通过以下方式设置时才有效:
shopt -s globstar
(默认情况下已禁用)且仅限于bash
的相对较新版本。
我相信zsh也支持这种语法。
重要的是要记住,通配符是由shell扩展的,而不是ls
命令。如果您键入ls **
或ls *.txt
,ls
命令本身永远不会看到*
字符;它只能看到扩展的文件列表,就像你在命令行上输入了整个列表一样。
答案 1 :(得分:35)
通过使用双星号(**
),您正在使用 glob 列出文件系统上的文件。 Glob是用于匹配文件路径的文字或通配符的字符串。使用一个或多个glob在文件系统上定位文件称为 globbing 。
除Linux shell外,globbing还用于各种配置文件中以指定要查找的文件列表。例如:.gitignore
文件中要忽略的文件和文件夹,Typescript项目中files
文件中的include
和tsconfig.json
选项等。
以下是其中一些最重要的方面,双星号(**
)是其中之一:
/
)分隔符始终是/
字符。段是两个分隔符之间的所有内容。
示例:Tests/HelloWorld.js
此处,Tests
和HelloWorld.js
是分段,/
是分隔符。
*
)单个星号(*
)在 one 段中匹配零个或多个字符。用于将文件放在一个目录中。
示例:*.js
此glob将匹配文件HelloWorld.js
,但不匹配文件Tests/HelloWorld.js
或Tests/UI/HelloWorld.js
**
)双星号(**
)在多个段中匹配零个或多个字符。它用于遍历嵌套目录中的文件。
示例:Tests/**/*.js
在这里,文件选择将限于Tests
目录。全局文件将匹配文件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
目录中排除所有文件和文件夹。
就是这样!希望有帮助!
答案 2 :(得分:5)
此特定通配符的确切行为已被其他答案很好地涵盖,但有关一般情况的信息可能有用。
此行为不仅限于ls
,也称为“globbing”,它是基于与现有文件名匹配的模式扩展。请务必注意,这些模式不使用正则表达式语法。
shell在将参数发送到程序之前对其进行预处理。通常有多种扩展级别,其中一些涉及全球化。
有关文件glob模式中可用的其他通配符的更多信息的一个很好的资源是unix联机帮助页。可以找到glob的在线版本here。
最后,这是一个简单的例子,说明这可以为你做什么,特别是当与其他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
结合使用时想象该实用程序等等。
答案 3 :(得分:5)
虽然其他一个或多个答案可能是正确的,但它们有点难以理解,尤其是如果您是像我这样的视觉人士。
所以我决定提供一个经过测试完全证实的视觉答案。
我创建了以下目录结构,每一级有两个文件“f”,一个有文件扩展名,一个没有文件扩展名,然后在达尔文的 Bash 中使用以下命令测试下面表头中的所有模式启用 globstar:stat -f "%N" <pattern>
。
如果您是一个有视觉的人,与仅仅阅读表格中的定义相比,查看表格可以让您更深入地了解**
的含义其他好的答案。
.
├── f
├── f.txt
└── x
├── f
├── f.txt
└── y
├── f
├── f.txt
└── z
├── f
└── f.txt
比较 *
和 **
:
* |
** |
x/* 或 */* |
x/** 或 */** |
*/*.* |
**/*.* |
*/ |
**/ |
|
---|---|---|---|---|---|---|---|---|
f |
✅ | ✅ | ||||||
f.txt |
✅ | ✅ | ✅ | |||||
x |
✅ | ✅ | ✅ | ✅ | ✅ | |||
x/f |
✅ | ✅ | ✅ | |||||
x/f.txt |
✅ | ✅ | ✅ | ✅ | ✅ | |||
x/y |
✅ | ✅ | ✅ | ✅ | ||||
x/y/f |
✅ | ✅ | ||||||
x/y/f.txt |
✅ | ✅ | ✅ | |||||
x/y/z |
✅ | ✅ | ✅ | |||||
x/y/z/f |
✅ | ✅ | ||||||
x/y/z/f.txt |
✅ | ✅ | ✅ |
匹配 .txt
个文件:
*.txt |
*/*.txt |
x/*/*.txt |
**/*.txt |
x/**/*.txt |
|
---|---|---|---|---|---|
f |
|||||
f.txt |
✅ | ✅ | |||
x |
|||||
x/f |
|||||
x/f.txt |
✅ | ✅ | ✅ | ||
x/y |
|||||
x/y/f |
|||||
x/y/f.txt |
✅ | ✅ | ✅ | ||
x/y/z |
|||||
x/y/z/f |
|||||
x/y/z/f.txt |
✅ | ✅ |
答案 4 :(得分:1)
与DOS dir
命令类似,ls
命令的功能是列出文件和目录。当要列出的东西是文件时,命令只列出文件,没什么大不了的。当要列出的东西是文件夹时,该命令列出文件夹的内容。此外,如果只是没有参数的ls
命令,则列出的默认内容是工作目录或当前文件夹。 (此外,当前文件夹的名称始终为.
,因此裸ls
命令等同于ls .
。)
示例:您在当前文件夹中有一个名为file_001
的文件,一个名为folder_002
的文件夹,并且在该文件夹中包含名为picture_003
和picture_004
的文件。当您输入ls
时,您会看到file_001 folder_002
,当您输入ls folder_002
时,您会看到picture_003 picture_004
。
在Unix中,通配符处理由shell执行。当您键入ls **
时,您的shell会在运行**
命令之前处理ls
,它会将**
替换为匹配的所有文件/文件夹的名称。 (*
通配符匹配任何文件或文件夹。使用**
匹配任何名称以任何内容开头且以任何内容结尾的文件或文件夹,因此它在功能上等同于{{ 1}}。)子>
在这种情况下,当运行*
命令时,命令行参数是当前文件夹中所有文件和文件夹的列表,就像您自己输入了它们一样。因此,在我们的示例中,您现在正在运行命令ls
。当ls file_001 folder_002
命令处理其命令行时,第一项是文件,因此它只列出文件,第二项是文件夹,因此它列出了文件夹的内容。此外,由于该命令列出了多个内容,因此它会打印带有文件夹名称的标签,因此您可以将输出列表中文件夹的内容与列出的其他内容区分开来。因此,命令ls
的输出将如下所示:
ls **
但是,我很好奇。哪些指南,书籍或文档建议您尝试使用命令file_001
folder_002:
picture_003 picture_004`
?
答案 5 :(得分:-15)
Keith's answer is the correct one. Refer there.
考虑以下目录树:
folderA
├── file1
├── file2
└── folderB
├── file3
└── folderC
ls
将列出当前文件夹中的所有对象:
$ ls
file1 file2 folderB
ls *
将列出当前文件夹中的所有对象,另外还会递归另一个级别
$ ls *
file1 file2
folderB:
file3 folderC
ls **中的第二个*在大多数情况下都不相关,因为shell扩展了通配符,ls得到了第一个*
的结果当启用globstar shell选项并在文件名扩展上下文中使用''时,用作单个模式的两个相邻的''将匹配所有文件以及零个或多个目录和子目录