问题描述
这工作正常:
$ echo email_{ldn,nyk,asp}.log
同样,我想找到略有不同的文件名:
$ find ~ -type f -name email_{ldn,asp}.log
但是上面的命令会导致错误:
find: paths must precede expression: email_nyk.log
非常感谢 find 命令中有关大括号扩展的任何帮助。
解决方法
错误消息是由您的 shell 扩展模式引起的。
假设您的当前目录中有 email_ldn.log
、email_nyk.log
和 email_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,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"
,
如果你想用一个前缀查找所有文件,你可以使用这个命令:
find ~ -type f -name "email_*.log"
在这种情况下,您不需要使用大括号。不要忘记在名称模式前后放置 "
(引号)。
find
不支持大括号来设置替代项,就像 shell 一样。因此,如果您想查找特定文件,可以分两步完成:首先查找所有带有“email”前缀的文件,然后使用 grep 查找特定文件。试试这个:
find ~ -type f -name "email*" | egrep "email_(ldn|asp|nyk).log"
大括号扩展不是做这种事情的方式,eval
是邪恶的,但你可以这样做:
eval find ~ -type f -and \\\( -false "-or -name "email_{ldn,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
会更好:
由于目的是找到匹配大括号扩展的文件并在之后执行很少的命令,所以 xargs
非常适合这个目的。
$ ls ~/email_{ldn,asp}.log | xargs -I %% sh -c 'chomd 644 %% && cp -arf %% ~/feed_dir'