假设我们在当前目录中使用 find 与音频文件(例如 MP3)和(重要的!)还有非 mp3 文件(例如 JPEG)存在于当前目录或其下方的某处。
除此之外,我们在那里有一个目录,其中包含一些其他音频文件(在示例中称为exclude_me),通过从文件搜索中排除,它应该符合其名称:
find . \( -type d -name 'exclude_me' -prune \) -o \( -type f -a -iname '*.mp3' -a -print \)
Run Code Online (Sandbox Code Playgroud)
(虽然在这种情况下不是绝对必要的,-a
但为了清楚起见,我特意设置了一些多余的括号,以及额外的运算符。)
由于显式-print
选项(参见http://mywiki.wooledge.org/UsingFind),这确实会省略“exclude_me”目录中的任何内容,并且仅从当前目录递归列出 *.mp3 文件。有时(并非总是)该alias
命令对于find
单行代码可能已经足够了,但该命令将需要在行尾的参数。
录取通知书的“* .MP3”参数-iname是之前的-print
在这种情况下,似乎没有办法与解决的问题alias
。
但是为什么不通过简单地交换两个选项来假装在数学中呢?
像这样:
find . \( -type d -name 'exclude_me' -prune \) -o \( -type f -a -print -a -iname '*.mp3' \)
Run Code Online (Sandbox Code Playgroud)
请记住,我设置了一个前提条件,即在 . 目录或其子目录。它已被设置为更清楚地证明这在引擎盖下无法按预期工作。没有它们,事情只会看起来工作正常。尽管单行中有不同的规范,但让它们出现将导致非 mp3 文件也被列出-iname '*.mp3'
。那么为什么-a
运算符不像数学中的那样工作,其中“A + B”与“B + A”相同?或者,在以下find
方面:
\( -type f -a -print -a -iname '*.mp3' \)
Run Code Online (Sandbox Code Playgroud)
应该是一样的
\( -type f -a -iname '*.mp3' -a -print \)
Run Code Online (Sandbox Code Playgroud)
或不?
有没有办法获得所需的结果并-iname
在行尾有参数,而不是介于两者之间?(除了丑陋的hackish解决方案,如grep -v exclude_me
之类的)
and
并且or
在许多编程语言中不是可交换的,例如 C、C++、C?、shells、find 等等。
他们使用从左到右评估的懒惰,即它首先评估左侧的术语,然后仅在需要时评估右侧的术语。所以在false and b
,b
不被评估,因为答案总是错误的。但是在b and false
,b
被评估,因为它还没有看到第二项是假的。
当术语是纯函数即谓词(返回布尔值且不执行其他任何操作)时,这没有任何区别,但是当它执行某些操作(有副作用)时,这很重要。
-print
做某事。它打印,因此很重要。
注意,任何允许副作用(例如 -print)的系统都必须定义评估顺序,从左到右可能是最简单的。