我有一个文件列表如下:
$ echo *
add akfefg aka ab ba
我想以任一顺序回显包含“a”和“b”的文件名。我试过
echo *[ab]*[ba]*
aka ab ba
它还打印“aka”。我试过了
$ echo *a*b* && echo *b*a*
ab
ba
它完成了它的工作,但是'ba'打印在下一行。有没有更简单的方法来做到这一点?谢谢。
答案1
在这个答案中,我正在解决两种不同的场景:
- 您想要匹配当前目录中同时包含
a
和的文件名b
然后你想对这些文件做一些事情。 - 您想要处理两个命令的输出
echo
以删除换行符。
如果您想循环文件名,那么最好有一个匹配所有名称的模式,然后在循环中使用该模式的扩展。echo
不建议使用,因为这会消除各个文件名之间的区别。
在zsh
shell 中,单个模式(*a*b*|*b*a*)
将扩展到字母a
和b
以任意顺序出现的所有名称。
在bash
shell 中,您可以使用单个扩展的通配模式(或ksh
类似通配模式)@(*a*b*|*b*a*)
来执行相同的操作。默认情况下, shellbash
不启用扩展通配模式,因此您需要首先启用它们shopt -s extglob
。
因此,在bash
shell 中,您可以使用类似的东西
shopt -s extglob
for name in @(*a*b*|*b*a*); do
# process "$name" here
done
生成所需文件名的另一种方法用于加工是通过使用find
:
find . ! -name . -prune -name '*a*' -name '*b*'
这会(仅)在当前目录中查找同时包含a
和的任何名称b
。然后,您可以-exec
在此命令末尾使用调用一些其他实用程序来执行操作,例如使用
find . ! -name . -prune -name '*a*' -name '*b*' -exec sh -c '
for name do
# process "$name" here
done' sh {} +
此处,find
生成内联sh -c
脚本使用的文件名。也可以看看了解“find”的 -exec 选项
然而,如果这是一个文本处理练习目的是将两行或多行文本(两次echo
调用的输出)排列成一行,然后您可以通过将文本通过管道传输来完成此操作paste -s -
。这还将删除文件名中嵌入的任何换行符。以这种方式使用paste
而不是tr -d '\n'
(这也会删除换行符)可确保生成的文本在末尾由单个换行符终止。
答案2
无需使用方括号,它们可以匹配某个范围内的字符。在第二个示例中,您使用了&&
运算符,它用于按顺序执行多个命令。这就是文件逐行打印的原因。
赶紧跑$ echo *a*b* *b*a*
这将在一行中打印所有文件。
编辑冗余匹配,例如cacbca
;
可以使用扩展通配符,首先在 bash 中启用它$ shopt -s extglob
然后将模式重新定义为:
$ printf '%s ' @(*a*b*|*b*a*)
@(pattern-list) 匹配给定模式之一