# match

## Synopsis

    match volume header
    match alternate volume header
    match journal
    match journal information block
    match catalog file
    match attributes file
    match startup file
    match extents file
    match allocation file
    match bad block file

    match files where <match-expr>

## Description

Defines the conditions under which a class will match a file. If more than one match specification is given for a class, a match of any one of the specifications will cause the class to match.

`match` may be followed either by the name of a volume data structure, or alternatively by the phrase `files where`, followed by a match expression. We recommend that you avoid the form with the volume data structure names, as it is really intended for use in the built-in class set definitions.

Match expressions are compiled into a form that iDefrag can interpret quickly to keep extent classification fast; most expressions compile and execute quickly, but a few impose a compile time or match-time penalty (there is a table later in this description that lists potentially problematic constructs).

Tip

Some match expressions have a performance penalty associated with them. Check out the Performance Tips section below for more information.

A match-expr or match expression is a Boolean expression consisting of comparisons of properties and values, logical operators and a few other predicates. Currently supported properties are

Property | Description | Can compare with
--- | --- | ---
name | The name of the file. | A string or regular expression
id | The catalog node ID of the file. | A number
size | The size of the file; this uses the size of the data fork, if present, or the resource fork otherwise. | A number
creator | The four character creator code for this file. | A number, string or regular expression
type | The four character type code for this file. | A number, string or regular expression
content modification date | The last time at which the file was modified. | A string or number of seconds since 1970
attribute modification date | The last time at which the file’s attributes were modified. | A string or number of seconds since 1970
access date | The last time at which the file was accessed. | A string or number of seconds since 1970
creation date | The time at which the file was created. | A string or number of seconds since 1970
backup date | The time at which the file was backed-up. | A string or number of seconds since 1970
owner | The UID of the owner of the file. | A number
group | The GID of the group of the file. | A number
mode | The file’s UNIX mode. | A number
admin flags | The file’s administrative flags. | A number
owner flags | The file’s owner-specific flags. | A number
resource fork size | The total size of the file’s resource fork. | A number
data fork size | The total size of the file’s data fork. | A number
containing folder | The folder immediately containing the file (for sorting, this property refers to the catalog node ID of the containing folder, not the name). | A string, regular expression, or the catalog ID of the folder

The operators are for the most part straightforward, with the possible exception of the `~=` and `~!=` operators (the match operators), which aside from their obvious use matching regular expressions against string properties can be used to match bitmasks against numeric properties. For instance, `0b1010 ~= 0b0010` is true, whilst `0b1010 ~= 0b0001` and `0b1010 ~!= 0b1000` are both false. (Note that having constants on both sides of an expression is not actually supported by iDefrag; the example is for illustrative purposes only.) A summary of the available operators is given below, in order of precedence:

Operator | Example | Description
--- | --- | ---
(...) | (size > 1024 or owner = 501) and (creator != 0 or type != 0) | Used to disambiguate expressions by explicitly grouping terms
not | not (size > 1024 or owner = 501) | Inverts the given expression
= | size = 1024 | True if the property is equal to the value
name = “Foo”
!= | size != 1024 | True if the property is not equal to the value
name != “Foo”
< | size < 1024 | True if the property is less than the value
name < “Foo”
> | size > 1024 | True if the property is greater then the value
name > “Foo”
<= | size <= 1024 | True if the property is less than or equal to the value
name <= “Foo”
>= | size >= 1024 | True if the property is greater than or equal to the value
name >= “Foo”
~= | mode ~= 0022 | For numeric values, matches if the bits set in the value are also set in the property For string values, matches if the regular expression specified in the string matches the property
name ~= “Foo(bar)?”
~!= | size ~!= 0022 | For numeric values, matches if the bits set in the value are not set in the property For string values, matches if the regular expression specified in the string does not match the property
name ~!= “Foo(bar)?”
and | size >= 1024 and name >= “Foo” | True if both expressions are true If the left hand side is false, the right hand side is never evaluated
or | size >= 1024 or name >= “Foo” | True if either expression is true If the left hand side is true, the right hand side is never evaluated

iDefrag also supports four predicate expressions, namely:

Expression | Meaning
--- | ---
file is within “folder” | True if the file is within the specified folder or any of its subfolders. Note the difference between `file is within "folder"` and `containing folder = "folder"`; the latter only tests if the file is immediately inside the specified folder, and does not look in subfolders.
file isn’t within “folder” | True if the file is not within the specified folder or any of its subfolders.
file is fragmented | True if either the data or resource fork of the file is fragmented.
file isn’t fragmented | True if both the data and resource fork of the file are not fragmented. Note that the data fork may not be contiguous with the resource fork.

## Performance Tips

Certain type of match expression have a substantial effect on performance, either during compilation of the match engine, or at match time when iDefrag is attempting to match file extents with classes.

Tip

If you need to use an expensive expression, try to restrict it so that it will only be evaluated when absolutely necessary.

A good way to do this is to put the expensive expression in the right hand side of an `and` or `or` expression, as those operators only evaluate the right hand side if they are unable to determine the result from the left hand side.

The table below lists the expressions that are potentially expensive.

Expression | Penalty at | Why?
--- | --- | ---
file is within “folder” | Compile | At compile time, iDefrag will search the folder and all subfolders to build a list of catalog IDs for all subfolders. This can be expensive for deep hierarchies like `/usr`.
file isn’t within
containing folder ~= <regexp> | Match | Regular expression matching must be performed at match time. Also forces iDefrag to find the full path of the folder at match time (this is very expensive).
containing folder ~!= <regexp>
name ~= <regexp> | Match | Regular expression matching must be performed at match time. If regexp starts with a “/” character, it is assumed that it will match a full path, which forces iDefrag to find the full path of the file at match time (this is very expensive).
name ~!= <regexp>
containing folder >= <string> | Match | Forces iDefrag to find the full path of the folder at match time (this is very exprensive). This problem does not exist for the `=` and `!=` operators.
containing folder > <string>
containing folder <= <string>
containing folder < <string>
name >= <string> | Match | If string starts with a “/” character, it is assumed that it is a full path, which forces iDefrag to find the full path of the file at match time (this is very expensive). This problem does not exist for the `=` and `!=` operators.
name > <string>
name <= <string>
name < <string>

Match time penalties are generally more problematic than compile-time penalties because matching processes very large numbers of files on a typical disk.

The most serious performance issue is if iDefrag is forced to look up the full paths for large numbers of items at match time. It’s best to avoid full path matching except with the `=` and `!=` operators if at all possible, and if you must use it in other circumstances then put it on the right hand side of an `and` or `or` expression.

Additionally, iDefrag runs matching in class priority order, so it’s better to put expensive match statements in classes that have a lower priority, so that files that match other class sets are not subject to the performance penalty from evaluating an expensive match expression against them.

## Example

    class "BSD" {
      match files where file is within "/usr" or file is within "/bin"
      match files where file is within "/etc"
      color "#ffe000"
    }

    class "Big" {
      match files where size > 104857600
      color "#ff00ff"
    }

## See also

class, display class, priority