以下是find
我尝试运行的命令的一些示例。我正在寻找不同的方法,我可以使用通配符来生成(作为示例)带有连接在一起的谓词的查找命令。
不起作用,因为find
每个之前需要一个 -name ,每个之间需要一个 -o 。
find . -name \*.{sh,pl,sql}
#find . -name *.sh *.pl *.sql
由于尾随而不起作用-o
。可以在那里提出一个肯定会失败的论点,但并不理想。另外,我的快捷方式现在比我的输出长。
find . `for X in {sh,pl,sql}; do echo -name \\\*.$X -o ;done`
#find . -name \*.sh -o -name \*.pl -o -name \*.sql -o
失败,因为它们被分组为一个参数 ( find: unknown predicate '-name *.sh'
)。此外,仍然表现出缺乏与 -o 的连接。
find . -name\ \*.{sh,pl,sql}
有效,但不涉及通配符(回复:非答案):
find . -regex '.*\(sh\|pl\|sql\)'
答案1
恕我直言,这个-false
想法是关键。我只是补充一下:
find . -false $(echo "-o -name *."{sh,pl,sql})
您只需引用所有内容即可使 bash 重复整个模式,包括-o -name
,然后通过从子 shell 返回它来“破坏”由引用所做的分组。这种方法的问题是模式中的引号不起作用。
编辑:有关此解决方案的另一个陷阱,请参阅 Michał Šrajer 的评论。请注意,您不能只在星号前放置一个反斜杠:命令替换返回 a *
,它将被扩展,或者 a \*
,它将按原样传递给 find (!)。至少,我当地的 bash 就是这样运作的。
这是我能做的最好的事情:
(GLOBIGNORE='*:.*'; find . \( -false $(echo "-o -name *."{sh,pl,sql,xml}) \) -print)
祝你好运 :)
顺便说一句,如果你是不是要添加更多参数find
,当然只需使用xargs
;在这种情况下,它可以完美地工作,带有引号和所有内容:
echo "-o -name *."{sh,pl,sql} | xargs find . -false
答案2
find
不使用glob()
.它用fnmatch()
。这就是为什么-name
谓词中唯一可用的元字符是*
、?
和。[
]
为了解决尾随问题,-o
我建议将其放入括号和添加额外的-false
谓词:
( -name AAA -o -name BBB -o -name CCC -o -false )
答案3
我假设这是这里的一个示例,并且您对一种允许您将模式组合成一个参数(即)find
的解决方案不感兴趣。有两种可能的方法:您可以构建一个字符串,并让 shell 将其拆分为多个参数(只要有空格),或者您可以构建一个数组。find
-regex
通过使用命令替换的字符串构建方法,它并不比您的尝试容易得多。
find . $(for X in sh pl sql; do echo "-name \\*.$X" -o; done | sed 's/-o *$//')
您还可以在命令之前循环构建字符串find
;我认为这将使脚本更加清晰。
find_options=
for x in sh pl sql; do
find_options="$find_options -o -name \\*.$x"
done
find_options=${find_options# -o}
find . $find_options
如果您的 shell 支持数组(即 bash、ksh 或 zsh),我建议您使用它们,这样您就不必插入额外的引号。
find_options=()
for x in sh pl sql; do
find_options+=(-o -name "*.$x")
done
unset "find_options[0]"
find . "${find_options[@]}"
1在命令行上,您无需担心可移植性,并且可以根据需要引用尽可能少的内容,因为您不必担心用户输入。您可以通过复制粘贴来处理重复。