我无法从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.
。
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
如何只显示一个文件?
答案1
Bash 没有功能可以仅扩展多个匹配项中的一个。
该模式@(foo)
仅匹配一个发生的图案foo
。也就是说,它匹配foo
,但不匹配foofoo
。这种语法形式对于构建 或 之类的模式很有用@(foo|bar)
,它匹配foo
或bar
。它可以用作较长模式的一部分,例如@(foo|bar)-*.txt
, 匹配foo-hello.txt
, foo-42.txt
,bar-42.txt
等。
如果要使用多个匹配项中的一个,可以将匹配项放入一个数组中,然后使用该数组的一个元素。
kernels=(vmlinuz*)
ls -l "${kernels[0]}"
匹配项始终按字典顺序排序,因此这将按字典顺序打印第一个匹配项。
请注意,如果模式与任何文件都不匹配,您将获得一个包含单个元素的数组,该元素是未更改的模式:
$ a=(doesnotmatchanything*)
$ ls -l "${a[0]}"
ls: cannot access doesnotmatchanything*: No such file or directory
设置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
Zsh 这里有方便的功能。这全局限定符 [NUM]
导致模式扩展到仅第 NUM 个匹配;该变体扩展到第 NUM1 个到第 NUM2 个匹配项(从 1 开始)。[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])
如果没有文件匹配,则glob 限定符N
会导致模式扩展为空列表。
kernels=(vmlinuz*(N))
if ((#kernels)); then
ls -l $kernels
else
echo "No kernels here"
fi
glob 限定符om
通过增加年龄而不是按名称(m
用于修改时间)对匹配项进行排序;Om
按年龄递减排序。因此vmlinuz*(om[1])
扩展到最新的内核文件。
答案2
“一场比赛”并不意味着你所认为的那样。它的意思是模式内的一场比赛,而不是只返回一个文件。ls
没有这样的选项。通常,人们会做类似的事情ls |head -1
。