2022-12-30 10:13:00 +01:00
|
|
|
#+TITLE: MU QUERY
|
|
|
|
#+MAN_CLASS_OPTIONS: :section-id "@SECTION_ID@" :date "@MAN_DATE@"
|
2022-12-17 23:21:52 +01:00
|
|
|
|
|
|
|
* NAME
|
|
|
|
|
2024-03-02 13:00:31 +01:00
|
|
|
mu-query - a language for finding messages in *mu* databases.
|
2022-12-17 23:21:52 +01:00
|
|
|
|
|
|
|
* DESCRIPTION
|
|
|
|
|
2023-09-12 18:07:11 +02:00
|
|
|
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
|
2022-12-17 23:21:52 +01:00
|
|
|
query-parser, but is an independent implementation that is customized for the
|
|
|
|
mu/mu4e use-case.
|
|
|
|
|
2023-09-12 18:07:11 +02:00
|
|
|
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.
|
2022-12-17 23:21:52 +01:00
|
|
|
|
2023-09-12 18:07:11 +02:00
|
|
|
Furthermore, *mu find* provides the ~--analyze~ option, which shows how *mu*
|
|
|
|
interprets your query; see the *ANALYZING QUERIES* section below.
|
2022-12-17 23:21:52 +01:00
|
|
|
|
|
|
|
*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
|
2024-03-02 14:25:56 +01:00
|
|
|
`banana' or `hello', or words prefixed with a field-name which makes them apply
|
2023-09-09 10:43:28 +02:00
|
|
|
to just that field. See *mu info fields* for all the available fields.
|
2022-12-17 23:21:52 +01:00
|
|
|
|
|
|
|
Some example queries:
|
|
|
|
#+begin_example
|
|
|
|
vacation
|
|
|
|
subject:capybara
|
|
|
|
maildir:/inbox
|
|
|
|
#+end_example
|
|
|
|
|
2024-03-02 14:25:56 +01:00
|
|
|
Terms without an explicit field-prefix, (like `vacation' above) are interpreted
|
2022-12-17 23:21:52 +01:00
|
|
|
like:
|
|
|
|
#+begin_example
|
|
|
|
to:vacation or subject:vacation or body:vacation or ...
|
|
|
|
#+end_example
|
|
|
|
|
2024-03-02 14:25:56 +01:00
|
|
|
The language is case-insensitive for terms and attempts to `flatten' diacritics,
|
2023-09-12 18:07:11 +02:00
|
|
|
so =angtrom= matches =Ångström=.
|
2022-12-17 23:21:52 +01:00
|
|
|
|
|
|
|
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
|
2023-09-12 18:07:11 +02:00
|
|
|
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.
|
2022-12-17 23:21:52 +01:00
|
|
|
|
|
|
|
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
|
2023-09-09 10:43:28 +02:00
|
|
|
unary *not*, with the conventional rules for precedence and association. The
|
|
|
|
operators are case-insensitive.
|
2022-12-17 23:21:52 +01:00
|
|
|
|
2023-09-12 18:07:11 +02:00
|
|
|
You can also group things with *(* and *)*, so you can write:
|
2022-12-17 23:21:52 +01:00
|
|
|
#+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.
|
|
|
|
|
2024-03-02 14:25:56 +01:00
|
|
|
Note that a =pure not= - e.g. searching for *not apples* is quite a `heavy' query.
|
2022-12-17 23:21:52 +01:00
|
|
|
|
|
|
|
* REGULAR EXPRESSIONS AND WILDCARDS
|
|
|
|
|
2023-08-19 12:39:17 +02:00
|
|
|
The language supports matching basic PCRE regular expressions, see *pcre(3)*.
|
2022-12-17 23:21:52 +01:00
|
|
|
|
|
|
|
Regular expressions are enclosed in *//*. Some examples:
|
2023-09-09 10:43:28 +02:00
|
|
|
|
2022-12-17 23:21:52 +01:00
|
|
|
#+begin_example
|
|
|
|
subject:/h.llo/ # match hallo, hello, ...
|
|
|
|
subject:/
|
|
|
|
#+end_example
|
|
|
|
|
2024-03-02 14:25:56 +01:00
|
|
|
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'
|
2022-12-17 23:21:52 +01:00
|
|
|
etc.
|
|
|
|
|
2023-09-09 10:43:28 +02:00
|
|
|
Wildcards are another mechanism for matching where a term with a rightmost ***
|
2022-12-17 23:21:52 +01:00
|
|
|
(and =only= in that position) matches any term that starts with the part before
|
2023-09-09 10:43:28 +02:00
|
|
|
the ***; they are therefore less powerful than regular expressions, but also much
|
|
|
|
faster:
|
2022-12-17 23:21:52 +01:00
|
|
|
#+begin_example
|
|
|
|
foo*
|
|
|
|
#+end_example
|
|
|
|
is equivalent to
|
|
|
|
#+begin_example
|
|
|
|
/foo.*/
|
|
|
|
#+end_example
|
|
|
|
|
2023-09-09 10:43:28 +02:00
|
|
|
Regular expressions can be useful, but are relatively slow.
|
2022-12-17 23:21:52 +01:00
|
|
|
|
|
|
|
* FIELDS
|
|
|
|
|
|
|
|
We already saw a number of search fields, such as *subject:* and *body:*. For the
|
2023-07-06 06:39:55 +02:00
|
|
|
full table with all details, including single-char shortcuts, try the command:
|
|
|
|
~mu info fields~.
|
2023-05-11 22:24:11 +02:00
|
|
|
|
2024-03-02 13:37:25 +01:00
|
|
|
#+ATTR_MAN: :disable-caption t
|
2024-03-17 09:59:37 +01:00
|
|
|
#+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
|
2023-05-11 22:24:11 +02:00
|
|
|
|
2023-09-09 10:43:28 +02:00
|
|
|
(*) The language code for the text-body if found. This works only if ~mu~ was
|
|
|
|
built with CLD2 support.
|
2022-12-17 23:21:52 +01:00
|
|
|
|
|
|
|
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=
|
2023-05-11 22:24:11 +02:00
|
|
|
and =bcc=).
|
|
|
|
|
|
|
|
Hence, for instance,
|
2022-12-17 23:21:52 +01:00
|
|
|
#+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
|
2023-09-09 10:43:28 +02:00
|
|
|
HH:MM:SS); you can leave out the right part and *mu* adds the rest, depending on
|
2022-12-17 23:21:52 +01:00
|
|
|
whether this is the beginning or end of the range (e.g., as a lower bound,
|
2024-03-02 14:25:56 +01:00
|
|
|
`2015' would be interpreted as the start of that year; as an upper bound as the
|
2022-12-17 23:21:52 +01:00
|
|
|
end of the year).
|
|
|
|
|
2024-03-02 14:25:56 +01:00
|
|
|
You can use `/' , `.', `-', `:' and `T' to make dates more human-readable.
|
2022-12-17 23:21:52 +01:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2024-03-02 14:25:56 +01:00
|
|
|
You can also use the special `dates' *now* and *today*:
|
2022-12-17 23:21:52 +01:00
|
|
|
#+begin_example
|
|
|
|
date:20170505..now
|
|
|
|
date:today..
|
|
|
|
#+end_example
|
|
|
|
|
2024-03-02 14:25:56 +01:00
|
|
|
Finally, you can use relative `ago' times which express some time before now and
|
2022-12-17 23:21:52 +01:00
|
|
|
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
|
2024-03-17 09:59:37 +01:00
|
|
|
+-----------+----------+----------+-----------------------------+
|
|
|
|
| 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 |
|
|
|
|
+-----------+----------+----------+-----------------------------+
|
2022-12-17 23:21:52 +01:00
|
|
|
#+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
|
|
|
|
|
2023-09-12 18:07:11 +02:00
|
|
|
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:
|
2022-12-17 23:21:52 +01:00
|
|
|
#+begin_example
|
|
|
|
maildir:/lists/running
|
|
|
|
#+end_example
|
|
|
|
|
2024-03-02 14:25:56 +01:00
|
|
|
Note the starting `/'. If you want to match mails in the `root' maildir, you can
|
|
|
|
do with a single `/':
|
2022-12-17 23:21:52 +01:00
|
|
|
#+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
|
|
|
|
|
2023-09-12 18:07:11 +02:00
|
|
|
And once again, note that when using the command-line, such queries must be
|
|
|
|
quoted:
|
2022-12-17 23:21:52 +01:00
|
|
|
#+begin_example
|
|
|
|
mu find 'maildir:"/Sent Items"'
|
|
|
|
#+end_example
|
|
|
|
|
2023-09-09 10:43:28 +02:00
|
|
|
Also note that you should *not* end the maildir with a ~/~, or it can be
|
|
|
|
misinterpreted as a regular expression term; see aforementioned.
|
|
|
|
|
2022-12-17 23:21:52 +01:00
|
|
|
* 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.
|
|
|
|
|
2024-03-02 14:25:56 +01:00
|
|
|
Find all messages with both `bee' and `bird' (in any field)
|
2022-12-17 23:21:52 +01:00
|
|
|
#+begin_example
|
|
|
|
bee AND bird
|
|
|
|
#+end_example
|
|
|
|
|
|
|
|
Find all messages with either Frodo or Sam:
|
|
|
|
#+begin_example
|
|
|
|
Frodo OR Sam
|
|
|
|
#+end_example
|
|
|
|
|
2024-03-02 14:25:56 +01:00
|
|
|
Find all messages with the `wombat' as subject, and `capybara' anywhere:
|
2022-12-17 23:21:52 +01:00
|
|
|
#+begin_example
|
|
|
|
subject:wombat and capybara
|
|
|
|
#+end_example
|
|
|
|
|
2024-03-02 14:25:56 +01:00
|
|
|
Find all messages in the `Archive' folder from Fred:
|
2022-12-17 23:21:52 +01:00
|
|
|
#+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
|
|
|
|
|
2024-03-02 14:25:56 +01:00
|
|
|
Find all messages written in Dutch or German with the word `hallo':
|
2023-05-11 22:24:11 +02:00
|
|
|
#+begin_example
|
|
|
|
hallo and (lang:nl or lang:de)
|
|
|
|
#+end_example
|
|
|
|
|
2023-09-12 18:07:11 +02:00
|
|
|
This is only available if your *mu* has support for this; see *mu info* and check
|
|
|
|
for "cld2-support*.
|
|
|
|
|
2023-09-09 10:43:28 +02:00
|
|
|
* ANALZYING QUERIES
|
2023-05-11 22:24:11 +02:00
|
|
|
|
2023-09-12 18:07:11 +02:00
|
|
|
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.
|
2022-12-17 23:21:52 +01:00
|
|
|
|
2023-09-09 10:43:28 +02:00
|
|
|
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
|
2022-12-17 23:21:52 +01:00
|
|
|
|
2023-09-12 18:07:11 +02:00
|
|
|
The ~parsed query~ is usually the most useful one for understanding how *mu*
|
|
|
|
interprets your query.
|
2022-12-17 23:21:52 +01:00
|
|
|
|
|
|
|
#+include: "prefooter.inc" :minlevel 1
|
|
|
|
|
|
|
|
* SEE ALSO
|
|
|
|
|
2023-07-06 06:39:55 +02:00
|
|
|
*mu-find(1)*, *mu-info(1), *pcre(3)*
|