【问题标题】:Unix brace expansion within find command查找命令中的 Unix 大括号扩展
【发布时间】:2021-07-15 10:46:19
【问题描述】:

这工作正常:

$ echo email_{ldn,nyk,asp}.log

同样,我想找到略有不同的文件名:

$ find ~ -type f -name email_{ldn,nyk,asp}.log

但是上面的命令会报错:

find: paths must precede expression: email_nyk.log

如果对 find 命令中的大括号展开提供任何帮助,我们将不胜感激。

【问题讨论】:

  • 您的操作系统到底是什么?你有 GNU find
  • 我使用的是 Linux 2.6.32 x86 64 GNU 版本。
  • edit您的问题添加所需的信息或澄清。

标签: linux shell find brace-expansion


【解决方案1】:

错误消息是您的 shell 扩展模式的结果。

假设您的当前目录中有文件email_ldn.logemail_nyk.logemail_asp.log,您的命令

find ~ -type f -name email_{ldn,nyk,asp}.log

将扩展为

find ~ -type f -name email_ldn.log email_nyk.log email_asp.log

这会导致错误消息。

为了防止 shell 扩展模式,您必须引用该模式。不幸的是,find 不支持在大括号中包含替代列表的模式,因此将此模式与 find 一起使用将不会按您预期的那样工作。

find ~ -type f -name "email_{ldn,nyk,asp}.log" # Does not work as intended.
find ~ -type f -name "email_*.log" # This would work, but matches other files as well.

如果您有 GNU find,则可以改用正则表达式。

find ~ -type f -regextype posix-extended -regex ".*/email_(ldn|nyk|asp).log"

【讨论】:

  • 感谢 Bodo 这么好的解释。
  • @JamesBond 如果这回答了您的问题,您可以通过单击复选标记接受答案。
【解决方案2】:

如果你想查找所有带有一个前缀的文件,你可以使用这个命令:

find ~ -type f -name "email_*.log"

在这种情况下,您不需要使用大括号。不要忘记在名称的模式前后加上"(引号)。

find 不支持大括号来设置替代项,就像 shell 一样。因此,如果要查找特定文件,可以分两步完成:首先查找所有带有“电子邮件”前缀的文件,然后 grep 查找特定文件。尝试这个: find ~ -type f -name "email*" | egrep "email_(ldn|asp|nyk).log"

【讨论】:

  • 这将匹配除 *.ldn.log 或 *.nyk.log 或 *.asp.log 之外的其他文件
  • 因此,您可以分两步执行此操作:首先您可以找到所有带有“电子邮件”前缀的文件,然后使用 grep 查找特定文件。试试这个:find ~ -type f -name "email*" | egrep "email_(ldn|asp|nyk).log" Find 不支持大括号来设置替代项,比如 echo 命令。
  • 感谢@Mikolaj 的回复,但我后来意识到这可以使用 xargs 来完成(我已在答案部分发布)
【解决方案3】:

大括号扩展不是做这种事情的方式,eval 是邪恶的,但你可以这样做:

eval find ~ -type f -and \\\( -false "-or -name "email_{ldn,nyk,asp}.log \\\)

主要思想是-name email_ldn.log email_nyk.log email_asp.log 不起作用,因为您希望表达式为-name email_ldn.log -or -name email_nyk.log -or -name email_asp.log,因此您使用大括号扩展创建该表达式。但随后find 接收-or -name email_???.log 作为单个参数而不是3 个参数,因此您需要使用eval 强制分词。总的来说,这是一个讨厌的、丑陋的解决方案。

【讨论】:

  • 代替 eval,xargs 将更适合这种类型的实现。请看我的下一条评论。
【解决方案4】:

最终在征服的过程中实现了,你们中的一些人建议使用eval,但我认为最好使用xargs

因为目标是找到匹配大括号扩展的文件并在之后执行少量命令,所以xargs很好地满足了这个目的。

$ ls ~/email_{ldn,nyk,asp}.log | xargs -I %% sh -c 'chomd 644 %% && cp -arf %% ~/feed_dir'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-24
    相关资源
    最近更新 更多