globstar: `**string*` 不会下降到子目录 `**/*string*` 中

globstar: `**string*` 不会下降到子目录 `**/*string*` 中

给出的是(子)目录中与字符串匹配的一组文件,例如:

find -name 'string' | sort
./1/2/3/4/string
./1/2/3/string
./1/2/string
./1/string
./string

为什么使用globstar来匹配文件,如

ls **string
string

无法运行目录,同时

ls **/string
1/2/3/4/string  1/2/3/string  1/2/string  1/string  string

成功了吗?根据我对页面描述的理解,man它应该匹配(子)目录,不是吗?

像这样的问题通常被标记为重复“ls * 、 ls ** 和 ls *** 的结果”,但那里的答案只处理ls **,它确实通过目录递归。似乎双星号后跟字符串会中断globstar

运行GNU bash v.4.4.19(1)mint 19


man bash

环球星

如果设置,路径名扩展上下文中使用的模式 ** 将匹配所有文件以及零个或多个目录和子目录。如果模式后跟 /,则仅目录和子目录匹配。

答案1

这在 Ksh 和 Zsh 中也是如此。

$ mkdir -p a/b/cdir
$ touch    a/b/cfile
$ ksh -c 'set -o globstar; echo **c*'
**c*
$ zsh -c 'echo **c*'
zsh:1: no matches found: **c*

在模式匹配下,Bash 的手册说:

globstar启用 shell 选项并*在文件名扩展上下文中使用时,*用作单个模式的两个相邻 s 将匹配所有文件以及零个或多个目录和子目录。

我想这可以理解为“单个模式”是由斜杠分隔的部分,因此foo/**/bar它处于单个模式中,但**bar事实并非如此。

不过,这可能会更清楚。

整个模式后面的尾部斜杠使模式仅匹配目录:

$ echo **/c*/
a/b/cdir/

答案2

当不受(仅)限制时,双精度*衰减到一的效果:*/

$ ls *c
abc  ac  acc  bc  cc  dc

$ ls **c
abc  ac  acc  bc  cc  dc

任何不是 a 的前导或尾随字符/都会导致**衰减:

这只是因为路径名(作为文件名)可以不是包含任何/.
a 不可能*扩展为包含 的名称/。 A**有点类似,它会扩展为包含以下内容的字符串/ 仅有的/当单独或由(不是任何其他字符/字符串)分隔时:

$ ls -d ./** | sort
./
./1
./1/2
./1/2/3
./1/2/3/4
./1/2/3/4/string
./1/2/3/string
./1/2/string
./1/string
./abc
./ac
./acc
./bc
./cc
./dc
./string

$ ls -d ./**c | sort 
./abc
./ac
./acc
./bc
./cc
./dc

$ ls -d ** | sort
1
1/2
1/2/3
1/2/3/4
1/2/3/4/string
1/2/3/string
1/2/string
1/string
abc
ac
acc
bc
cc
dc
string

$ ls -d **c | sort
abc
ac
acc
bc
cc
dc

$ ls -d **/ | sort
1/
1/2/
1/2/3/
1/2/3/4/

$ ls -d 1**/ | sort
1/

相关内容