Bash 扩展通配符

Fel*_*rez 7 bash wildcards

我无法从ls使用 bash 扩展通配符的输出中仅显示一个文件。

info bash

  If the `extglob' shell option is enabled using the `shopt' builtin,
several extended pattern matching operators are recognized.  In the
following description, a PATTERN-LIST is a list of one or more patterns
separated by a `|'.  Composite patterns may be formed using one or more
of the following sub-patterns:

`?(PATTERN-LIST)'
     Matches zero or one occurrence of the given patterns.

`*(PATTERN-LIST)'
     Matches zero or more occurrences of the given patterns.

`+(PATTERN-LIST)'
     Matches one or more occurrences of the given patterns.

`@(PATTERN-LIST)'
     Matches exactly one of the given patterns.

`!(PATTERN-LIST)'
     Matches anything except one of the given patterns.
Run Code Online (Sandbox Code Playgroud)

shops -s extglob

ls -l /boot/@(vmlinuz*)
-rw-r--r--  1 root root 1829516 Apr 21  2009 /boot/vmlinuz-2.6.9-89.EL
-rw-r--r--  1 root root 1700492 Apr 21  2009 /boot/vmlinuz-2.6.9-89.ELsmp

ls -l /boot/?(vmlinuz*)
-rw-r--r--  1 root root 1829516 Apr 21  2009 /boot/vmlinuz-2.6.9-89.EL
-rw-r--r--  1 root root 1700492 Apr 21  2009 /boot/vmlinuz-2.6.9-89.ELsmp
Run Code Online (Sandbox Code Playgroud)

如何只显示一个文件?

Gil*_*il' 6

Bash 没有功能可以仅扩展多个匹配项中的一个。

该模式@(foo)仅匹配该模式的一次出现foo。也就是说,它匹配foo,但不匹配foofoo。这种语法形式对于构建 或 之类的模式很有用@(foo|bar),它匹配foobar。它可以用作较长模式的一部分,例如,@(foo|bar)-*.txt匹配, , 等。foo-hello.txtfoo-42.txtbar-42.txt

如果要使用多个匹配项中的一个,可以将匹配项放入一个数组中,然后使用该数组的一个元素。

kernels=(vmlinuz*)
ls -l "${kernels[0]}"
Run Code Online (Sandbox Code Playgroud)

匹配项始终按字典顺序排序,因此这将按字典顺序打印第一个匹配项。

请注意,如果模式与任何文件都不匹配,您将获得一个包含单个元素的数组,该元素是未更改的模式:

$ a=(doesnotmatchanything*)
$ ls -l "${a[0]}"
ls: cannot access doesnotmatchanything*: No such file or directory
Run Code Online (Sandbox Code Playgroud)

设置nullglob选项以获取空数组。

shopt -s nullglob
kernels=(vmlinuz*)
if ((${#kernels[@]} == 0)); then
  echo "No kernels here"
else
  echo "One of the ${#kernels[@]} kernels is ${kernels[0]}"
fi
Run Code Online (Sandbox Code Playgroud)

Zsh 这里有方便的功能。glob限定符 导致模式扩展为仅第 NUM 个匹配项;该变体扩展到第 NUM1 个到第 NUM2 个匹配项(从 1 开始)。[NUM][NUM1,NUM2]

% ls -l vmlinuz*([1])
lrwxrwxrwx 1 root root 26 Nov 15 21:12 vmlinuz -> vmlinuz-3.16-0.bpo.3-amd64
% ls -l nosuchfilehere*([1])
zsh: no matches found: nosuchfilehere*([1])
Run Code Online (Sandbox Code Playgroud)

如果没有文件匹配,则glob 限定符N会导致模式扩展为空列表。

kernels=(vmlinuz*(N))
if ((#kernels)); then
  ls -l $kernels
else
  echo "No kernels here"
fi
Run Code Online (Sandbox Code Playgroud)

glob 限定符om通过增加年龄而不是按名称(m用于修改时间)对匹配项进行排序;Om按年龄递减排序。因此vmlinuz*(om[1])扩展到最新的内核文件。