多部分参数的 Bash 通配

多部分参数的 Bash 通配

以下是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在命令行上,您无需担心可移植性,并且可以根据需要引用尽可能少的内容,因为您不必担心用户输入。您可以通过复制粘贴来处理重复。

相关内容