# test - perform tests on files and text

## Synopsis

    test [EXPRESSION]
    [ [EXPRESSION] ]

## Description

`test` checks the given conditions and sets the exit status to 0 if they are true, 1 if they are false.

The first form (`test`) is preferred. For compatibility with other shells, the second form is available: a matching pair of square brackets (`[ [EXPRESSION] ]`).

When using a variable or command substitution as an argument with `test` you should almost always enclose it in double-quotes, as variables expanding to zero or more than one argument will most likely interact badly with `test`.

Warning

For historical reasons, `test` supports the one-argument form (`test foo`), and this will also be triggered by e.g. `test -n $foo` if $foo is unset. We recommend you don’t use the one-argument form and quote all variables or command substitutions used with `test`.

This confusing misfeature will be removed in future. `test -n` without any additional argument will be false, `test -z` will be true and any other invocation with exactly one or zero arguments, including `test -d` and `test "foo"` will be an error.

The same goes for `[`, e.g. `[ "foo" ]` and `[ -d ]` will be errors.

This can be turned on already via the `test-require-arg` feature flag, and will eventually become the default and then only option.

## Operators for files and directories

-b FILE

  Returns true if FILE is a block device.

-c FILE

  Returns true if FILE is a character device.

-d FILE

  Returns true if FILE is a directory.

-e FILE

  Returns true if FILE exists.

-f FILE

  Returns true if FILE is a regular file.

-g FILE

  Returns true if FILE has the set-group-ID bit set.

-G FILE

  Returns true if FILE exists and has the same group ID as the current user.

-k FILE

  Returns true if FILE has the sticky bit set. If the OS does not support the concept it returns false. See https://en.wikipedia.org/wiki/Sticky_bit.

-L FILE

  Returns true if FILE is a symbolic link.

-O FILE

  Returns true if FILE exists and is owned by the current user.

-p FILE

  Returns true if FILE is a named pipe.

-r FILE

  Returns true if FILE is marked as readable.

-s FILE

  Returns true if the size of FILE is greater than zero.

-S FILE

  Returns true if FILE is a socket.

-t FD

  Returns true if the file descriptor FD is a terminal (TTY).

-u FILE

  Returns true if FILE has the set-user-ID bit set.

-w FILE

  Returns true if FILE is marked as writable; note that this does not check if the filesystem is read-only.

-x FILE

  Returns true if FILE is marked as executable.

## Operators to compare files and directories

FILE1 -nt FILE2

  Returns true if FILE1 is newer than FILE2, or FILE1 exists and FILE2 does not.

FILE1 -ot FILE2

  Returns true if FILE1 is older than FILE2, or FILE2 exists and FILE1 does not.

FILE1 -ef FILE1

  Returns true if FILE1 and FILE2 refer to the same file.

## Operators for text strings

STRING1 = STRING2

  Returns true if the strings STRING1 and STRING2 are identical.

STRING1 != STRING2

  Returns true if the strings STRING1 and STRING2 are not identical.

-n STRING

  Returns true if the length of STRING is non-zero.

-z STRING

  Returns true if the length of STRING is zero.

## Operators to compare and examine numbers

NUM1 -eq NUM2

  Returns true if NUM1 and NUM2 are numerically equal.

NUM1 -ne NUM2

  Returns true if NUM1 and NUM2 are not numerically equal.

NUM1 -gt NUM2

  Returns true if NUM1 is greater than NUM2.

NUM1 -ge NUM2

  Returns true if NUM1 is greater than or equal to NUM2.

NUM1 -lt NUM2

  Returns true if NUM1 is less than NUM2.

NUM1 -le NUM2

  Returns true if NUM1 is less than or equal to NUM2.

Both integers and floating point numbers are supported.

## Operators to combine expressions

COND1 -a COND2

  Returns true if both COND1 and COND2 are true.

COND1 -o COND2

  Returns true if either COND1 or COND2 are true.

Expressions can be inverted using the ! operator:

! EXPRESSION

  Returns true if EXPRESSION is false, and false if EXPRESSION is true.

Expressions can be grouped using parentheses.

( EXPRESSION )

  Returns the value of EXPRESSION.

Note that parentheses will usually require escaping with `\` (so they appear as `\(` and `\)`) to avoid being interpreted as a command substitution.

## Examples

If the `/tmp` directory exists, copy the `/etc/motd` file to it:

    if test -d /tmp
        cp /etc/motd /tmp/motd
    end

If the variable `MANPATH` is defined and not empty, print the contents. (If `MANPATH` is not defined, then it will expand to zero arguments, unless quoted.)

    if test -n "$MANPATH"
        echo $MANPATH
    end

Be careful with unquoted variables:

    if test -n $MANPATH
        # This will also be reached if $MANPATH is unset,
        # because in that case we have `test -n`, so it checks if "-n" is non-empty, and it is.
        echo $MANPATH
    end

This will change in a future release of fish, or already with the `test-require-arg` feature flag - if $MANPATH is unset, `if test -n $MANPATH` will be false.

Parentheses and the `-o` and `-a` operators can be combined to produce more complicated expressions. In this example, success is printed if there is a `/foo` or `/bar` file as well as a `/baz` or `/bat` file.

    if test \( -f /foo -o -f /bar \) -a \( -f /baz -o -f /bat \)
        echo Success.
    end

Numerical comparisons will fail if one of the operands is not a number:

    if test 42 -eq "The answer to life, the universe and everything"
        echo So long and thanks for all the fish # will not be executed
    end

A common comparison is with `status`:

    if test $status -eq 0
        echo "Previous command succeeded"
    end

The previous test can likewise be inverted:

    if test ! $status -eq 0
        echo "Previous command failed"
    end

which is logically equivalent to the following:

    if test $status -ne 0
        echo "Previous command failed"
    end

## Standards

Unlike many things in fish, `test` implements a subset of the IEEE Std 1003.1-2008 (POSIX.1) standard. The following exceptions apply:

- The `<` and `>` operators for comparing strings are not implemented.

- With `test-require-arg`, the zero- and one-argument modes will behave differently.

> In cases such as this, one can use `command` `test` to explicitly use the system’s standalone `test` rather than this `builtin` `test`.

## See also

Other commands that may be useful as a condition, and are often easier to use:

- string - manipulate strings, which can do string operations including wildcard and regular expression matching

- path - manipulate and check paths, which can do file checks and operations, including filters on multiple paths at once