我经常需要找到一个文件,但我不确定该文件的名称是什么,如下所示:
$ find -iname '*foo*' -o -iname '*bar*' -o -iname '*blah*'
这有点乏味。我想创建一个更易于使用的别名,如下所示:
$ findany foo bar blah
这是我的尝试:
findany() {
args=("-iname" "'*$1*'")
shift
while [ $# -gt 0 ]; do
args+=("-o" "-iname" "'*$1*'")
shift
done
find ${args[@]}
}
问题是它永远不会产生任何结果,即使文件就在那里:
$ ls
bar.txt blah.txt foo.txt
$ findany foo bar blah
# nothing
如果我echo
在命令前面添加,它看起来是正确的:
$ findany foo bar blah
find -iname '*foo*' -o -iname '*bar*' -o -iname '*blah*'
如果我复制上面的输出并运行它,它就可以正常工作:
$ find -iname '*foo*' -o -iname '*bar*' -o -iname '*blah*'
./bar.txt
./foo.txt
./blah.txt
我认为这与参数分割或引号有关,但我不确定如何调试它。
我通常使用 zsh,但我在 bash 中验证了相同的行为。
你们非常接近!但由于某种原因,您在文件名本身中包含了单引号,因此它们永远不会匹配。
此外,您还必须引用
"${args[@]}"
才能使其正常工作。否则,它会受到分词的影响,并且任何 glob 都会在看到它们之前在 shell 中扩展find
。试试这个(特别是对于
bash
):使用 zsh,您可以使用:
要从数组构建该模式,您可以使用
j[|]
参数扩展标志来连接数组的元素,并|
与~
参数扩展标志结合使用,以便将其|
视为全局模式运算符,或者与~
参数扩展运算符结合使用,以便任何连接字符串中的通配符(即使是在数组元素中找到的通配符)也被视为模式。或者:
例如
findany1 '??'
会查找名称包含的文件??
,而findany2
会查找名称至少包含 2 个字符的文件。您需要findany2 '\?\?'
或findany2 '[?][?]'
查找名称??
包含findany2
.为了与 做出同样的区分
find
,那就是:我们用( /支持的唯一引用运算符)转义
find
(?
、*
和[...]
)识别的通配符。\
\
find
fnmatch()
这是解决问题的一种方法,但坦率地说,它的结果类似于
(但它不需要 的帮助就可以做到这一点
find
)。我们可以很快地构建一个 shell 脚本。
如果您想将其作为函数,只需将其放入
pattern=…
函数done
声明中即可。