Make the emphasis more consistent, and do it using underscores in Org documents, since verbatim is rendered as underlined anyway.
388 lines
13 KiB
Org Mode
388 lines
13 KiB
Org Mode
#+TITLE: MU QUERY
|
|
#+MAN_CLASS_OPTIONS: :section-id "@SECTION_ID@" :date "@MAN_DATE@"
|
|
#+include: macros.inc
|
|
|
|
* NAME
|
|
|
|
mu-query - a language for finding messages in *mu* databases.
|
|
|
|
* DESCRIPTION
|
|
|
|
The *mu* query language is the language used by *mu find* and *mu4e* to find messages
|
|
in *mu*'s Xapian database. The language is quite similar to Xapian's default
|
|
query-parser, but is an independent implementation that is customized for the
|
|
mu/mu4e use-case.
|
|
|
|
Here, we give a structured but informal overview of the query language and
|
|
provide examples. As a companion to this, we recommend the *mu fields* and *mu
|
|
flags* commands to get an up-to-date list of the available fields and flags.
|
|
|
|
Furthermore, *mu find* provides the *--analyze* option, which shows how *mu*
|
|
interprets your query; see the *ANALYZING QUERIES* section below.
|
|
|
|
*NOTE:* if you use queries on the command-line (say, for *mu find*), you need to
|
|
quote any characters that would otherwise be interpreted by the shell, such as
|
|
*""*, *(* and *)* and whitespace.
|
|
|
|
* TERMS
|
|
|
|
The basic building blocks of a query are *terms*; these are just normal words like
|
|
`banana' or `hello', or words prefixed with a field-name which makes them apply
|
|
to just that field. See *mu info fields* for all the available fields.
|
|
|
|
Some example queries:
|
|
#+begin_example
|
|
vacation
|
|
subject:capybara
|
|
maildir:/inbox
|
|
#+end_example
|
|
|
|
Terms without an explicit field-prefix, (like `vacation' above) are interpreted
|
|
like:
|
|
#+begin_example
|
|
to:vacation or subject:vacation or body:vacation or ...
|
|
#+end_example
|
|
|
|
The language is case-insensitive for terms and attempts to `flatten' diacritics,
|
|
so =angtrom= matches =Ångström=.
|
|
|
|
If terms contain whitespace, they need to be quoted:
|
|
#+begin_example
|
|
subject:"hi there"
|
|
#+end_example
|
|
This is a so-called =phrase query=, which means that we match against subjects
|
|
that contain the literal phrase "hi there". Phrase queries only work for fields
|
|
that are /indexed/, i.e., fields with *index* in the *mu info fields* search column.
|
|
|
|
Remember that you need to escape those quotes when using this from the
|
|
command-line:
|
|
#+begin_example
|
|
mu find subject:\\"hi there\\"
|
|
#+end_example
|
|
|
|
* LOGICAL OPERATORS
|
|
|
|
We can combine terms with logical operators -- binary ones: *and*, *or*, *xor* and the
|
|
unary *not*, with the conventional rules for precedence and association. The
|
|
operators are case-insensitive.
|
|
|
|
You can also group things with *(* and *)*, so you can write:
|
|
#+begin_example
|
|
(subject:beethoven or subject:bach) and not body:elvis
|
|
#+end_example
|
|
|
|
If you do not explicitly specify an operator between terms, *and* is implied, so
|
|
the queries
|
|
#+begin_example
|
|
subject:chip subject:dale
|
|
#+end_example
|
|
#+begin_example
|
|
subject:chip AND subject:dale
|
|
#+end_example
|
|
are equivalent. For readability, we recommend the second version.
|
|
|
|
Note that a =pure not= - e.g. searching for *not apples* is quite a `heavy' query.
|
|
|
|
* REGULAR EXPRESSIONS AND WILDCARDS
|
|
|
|
The language supports matching basic PCRE regular expressions, see {{{man-link(pcre,3)}}}.
|
|
|
|
Regular expressions are enclosed in *//*. Some examples:
|
|
|
|
#+begin_example
|
|
subject:/h.llo/ # match hallo, hello, ...
|
|
subject:/
|
|
#+end_example
|
|
|
|
Note the difference between `maildir:/foo' and `maildir:/foo/'; the former
|
|
matches messages in the `/foo' maildir, while the latter matches all messages in
|
|
all maildirs that match `foo', such as `/foo', `/bar/cuux/foo', `/fooishbar'
|
|
etc.
|
|
|
|
Wildcards are another mechanism for matching where a term with a rightmost ***
|
|
(and =only= in that position) matches any term that starts with the part before
|
|
the ***; they are therefore less powerful than regular expressions, but also much
|
|
faster:
|
|
#+begin_example
|
|
foo*
|
|
#+end_example
|
|
is equivalent to
|
|
#+begin_example
|
|
/foo.*/
|
|
#+end_example
|
|
|
|
Regular expressions can be useful, but are relatively slow.
|
|
|
|
* FIELDS
|
|
|
|
We already saw a number of search fields, such as *subject:* and *body:*. For the
|
|
full table with all details, including single-char shortcuts, try the command:
|
|
*mu info fields*.
|
|
|
|
#+ATTR_MAN: :disable-caption t
|
|
#+begin_example
|
|
+-----------+----------+----------+-----------------------------+
|
|
| flag | shortcut | category | description |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| draft | D | file | Draft (in progress) |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| flagged | F | file | User-flagged |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| passed | P | file | Forwarded message |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| replied | R | file | Replied-to |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| seen | S | file | Viewed at least once |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| trashed | T | file | Marked for deletion |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| new | N | maildir | New message |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| signed | z | content | Cryptographically signed |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| encrypted | x | content | Encrypted |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| attach | a | content | Has at least one attachment |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| unread | u | pseudo | New or not seen message |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| list | l | content | Mailing list message |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| personal | q | content | Personal message |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| calendar | c | content | Calendar invitation |
|
|
+-----------+----------+----------+-----------------------------+
|
|
#+end_example
|
|
|
|
(*) The language code for the text-body if found. This works only if *mu* was
|
|
built with CLD2 support.
|
|
|
|
There are also the special fields *contact:*, which matches all contact-fields
|
|
(=from=, =to=, =cc= and =bcc=), and *recip*, which matches all recipient-fields (=to=, =cc=
|
|
and =bcc=).
|
|
|
|
Hence, for instance,
|
|
#+begin_example
|
|
contact:fnorb@example.com
|
|
#+end_example
|
|
is equivalent to
|
|
#+begin_example
|
|
(from:fnorb@example.com or to:fnorb@example.com or
|
|
cc:from:fnorb@example.com or bcc:fnorb@example.com)
|
|
#+end_example
|
|
|
|
* DATE RANGES
|
|
|
|
The *date:* field takes a date-range, expressed as the lower and upper bound,
|
|
separated by *..*. Either lower or upper (but not both) can be omitted to create
|
|
an open range.
|
|
|
|
Dates are expressed in local time and using ISO-8601 format (YYYY-MM-DD
|
|
HH:MM:SS); you can leave out the right part and *mu* adds the rest, depending on
|
|
whether this is the beginning or end of the range (e.g., as a lower bound,
|
|
`2015' would be interpreted as the start of that year; as an upper bound as the
|
|
end of the year).
|
|
|
|
You can use `/' , `.', `-', `:' and `T' to make dates more human-readable.
|
|
|
|
Some examples:
|
|
#+begin_example
|
|
date:20170505..20170602
|
|
date:2017-05-05..2017-06-02
|
|
date:..2017-10-01T12:00
|
|
date:2015-06-01..
|
|
date:2016..2016
|
|
#+end_example
|
|
|
|
You can also use the special `dates' *now* and *today*:
|
|
#+begin_example
|
|
date:20170505..now
|
|
date:today..
|
|
#+end_example
|
|
|
|
Finally, you can use relative `ago' times which express some time before now and
|
|
consist of a number followed by a unit, with units *s* for seconds, *M* for minutes,
|
|
*h* for hours, *d* for days, *w* for week, *m* for months and *y* for years. Some
|
|
examples:
|
|
|
|
#+begin_example
|
|
date:3m..
|
|
date:2017.01.01..5w
|
|
#+end_example
|
|
|
|
* SIZE RANGES
|
|
|
|
The *size* or *z* field allows you to match =size ranges= -- that is, match messages
|
|
that have a byte-size within a certain range. Units (b (for bytes), K (for 1000
|
|
bytes) and M (for 1000 * 1000 bytes) are supported). Some examples:
|
|
|
|
#+begin_example
|
|
size:10k..2m
|
|
size:10m..
|
|
#+end_example
|
|
|
|
* FLAG FIELD
|
|
|
|
The *flag/g* field allows you to match message flags. The following fields are
|
|
available:
|
|
#+begin_example
|
|
+-----------+----------+----------+-----------------------------+
|
|
| flag | shortcut | category | description |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| draft | D | file | Draft (in progress) |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| flagged | F | file | User-flagged |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| passed | P | file | Forwarded message |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| replied | R | file | Replied-to |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| seen | S | file | Viewed at least once |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| trashed | T | file | Marked for deletion |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| new | N | maildir | New message |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| signed | z | content | Cryptographically signed |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| encrypted | x | content | Encrypted |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| attach | a | content | Has at least one attachment |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| unread | u | pseudo | New or not seen message |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| list | l | content | Mailing list message |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| personal | q | content | Personal message |
|
|
+-----------+----------+----------+-----------------------------+
|
|
| calendar | c | content | Calendar invitation |
|
|
+-----------+----------+----------+-----------------------------+
|
|
#+end_example
|
|
|
|
Some examples:
|
|
#+begin_example
|
|
flag:attach
|
|
flag:replied
|
|
g:x
|
|
#+end_example
|
|
|
|
Encrypted messages may be signed as well, but this is only visible after
|
|
decrypting and thus invisible to *mu*.
|
|
|
|
* PRIORITY FIELD
|
|
|
|
The message priority field (*prio:*) has three possible values: *low*, *normal* or
|
|
*high*. For instance, to match high-priority messages:
|
|
#+begin_example
|
|
prio:high
|
|
#+end_example
|
|
|
|
* MAILDIR
|
|
|
|
The Maildir field describes the directory path starting *after* the Maildir root
|
|
directory, and before the =/cur/= or =/new/= part. So, for example, if there's a
|
|
message with the file name _~/Maildir/lists/running/cur/1234.213:2,_, you could
|
|
find it (and all the other messages in that same maildir) with:
|
|
#+begin_example
|
|
maildir:/lists/running
|
|
#+end_example
|
|
|
|
Note the starting `/'. If you want to match mails in the `root' maildir, you can
|
|
do with a single `/':
|
|
#+begin_example
|
|
maildir:/
|
|
#+end_example
|
|
|
|
If you have maildirs (or any fields) that include spaces, you need to quote
|
|
them, ie.
|
|
#+begin_example
|
|
maildir:"/Sent Items"
|
|
#+end_example
|
|
|
|
And once again, note that when using the command-line, such queries must be
|
|
quoted:
|
|
#+begin_example
|
|
mu find 'maildir:"/Sent Items"'
|
|
#+end_example
|
|
|
|
Also note that you should *not* end the maildir with a ~/~, or it can be
|
|
misinterpreted as a regular expression term; see aforementioned.
|
|
|
|
* MORE EXAMPLES
|
|
|
|
Here are some simple examples of *mu* queries; you can make many more complicated
|
|
queries using various logical operators, parentheses and so on, but in the
|
|
author's experience, it's usually faster to find a message with a simple query
|
|
just searching for some words.
|
|
|
|
Find all messages with both `bee' and `bird' (in any field)
|
|
#+begin_example
|
|
bee AND bird
|
|
#+end_example
|
|
|
|
Find all messages with either Frodo or Sam:
|
|
#+begin_example
|
|
Frodo OR Sam
|
|
#+end_example
|
|
|
|
Find all messages with the `wombat' as subject, and `capybara' anywhere:
|
|
#+begin_example
|
|
subject:wombat and capybara
|
|
#+end_example
|
|
|
|
Find all messages in the `Archive' folder from Fred:
|
|
#+begin_example
|
|
from:fred and maildir:/Archive
|
|
#+end_example
|
|
|
|
Find all unread messages with attachments:
|
|
#+begin_example
|
|
flag:attach and flag:unread
|
|
#+end_example
|
|
|
|
Find all messages with PDF-attachments:
|
|
#+begin_example
|
|
mime:application/pdf
|
|
#+end_example
|
|
|
|
Find all messages with attached images:
|
|
#+begin_example
|
|
mime:image/*
|
|
#+end_example
|
|
|
|
Find all messages written in Dutch or German with the word `hallo':
|
|
#+begin_example
|
|
hallo and (lang:nl or lang:de)
|
|
#+end_example
|
|
|
|
This is only available if your *mu* has support for this; see *mu info* and check
|
|
for "cld2-support*.
|
|
|
|
* ANALZYING QUERIES
|
|
|
|
Despite all the excellent documentation, in some cases it can be non-obvious how
|
|
*mu* interprets your query. For that, you can ask *mu* to analyze the query -- that
|
|
is, show how *mu* interprets the query.
|
|
|
|
This uses the the *--analyze* option to *mu find*.
|
|
#+begin_example
|
|
$ mu find subject:wombat AND date:3m.. size:..2000 --analyze
|
|
,* query:
|
|
subject:wombat AND date:3m.. size:..2000
|
|
,* parsed query:
|
|
(and (subject "wombat") (date (range "2023-05-30T06:10:09Z" "")) (size (range "" "2000")))
|
|
,* Xapian query:
|
|
Query((Swombat AND VALUE_GE 4 n64759341 AND VALUE_LE 17 i7d0))
|
|
#+end_example
|
|
|
|
The ~parsed query~ is usually the most useful one for understanding how *mu*
|
|
interprets your query.
|
|
|
|
#+include: "prefooter.inc" :minlevel 1
|
|
|
|
* SEE ALSO
|
|
|
|
{{{man-link(mu-find,1)}}},
|
|
{{{man-link(mu-info,1)}}},
|
|
{{{man-link(pcre,3)}}}
|