From Bash's manual

6.4 Bash Conditional Expressions

Conditional expressions are used by the [[ compound command and the test and [ builtin commands.

Expressions may be unary or binary. Unary expressions are often used to examine the status of a file. There are string operators and numeric comparison operators as well. If the file argument to one of the primaries is of the form /dev/fd/N, then file descriptor N is checked. If the file argument to one of the primaries is one of /dev/stdin, /dev/stdout, or /dev/stderr, file descriptor 0, 1, or 2, respectively, is checked.

When used with [[, the ‘<’ and ‘>’ operators sort lexicographically using the current locale. The test command uses ASCII ordering.

Unless otherwise specified, primaries that operate on files follow symbolic links and operate on the target of the link, rather than the link itself.

What is the definition of a primary?

What is the difference between a primary and an operator or operation?

  • A "primary* is one of the "operands". Just jargon, which depends on the writer. Jan 10, 2016 at 14:20
  • 3
    In the quote, a primary looks like an operation or operator to me, rather than an operand
    – Tim
    Jan 10, 2016 at 14:37

4 Answers 4


As noted, this is jargon. The bash reference manual does not define the term; it is assumed that the reader knows about it.

You can easily find it used for operands in an arithmetic expression. See for example Arithmetic Expressions in a Fortran 77 Language Reference Manual, which says

A primary is the basic component in an arithmetic expression. The forms of a primary are the following:

  • an unsigned arithmetic constant

  • a symbolic name of an arithmetic constant

  • an arithmetic variable reference

  • an arithmetic array element reference

  • an arithmetic function reference

  • an arithmetic expression enclosed in parentheses

In POSIX, it is (still) used mostly relying upon the reader's prior knowledge of the term. For instance, in the shell command language, it refers to primaries of the find command:

(such as in the argument to the find - name primary when find is being called using one of the exec functions as defined in the System Interfaces volume of POSIX.1-2008, or in the pattern argument to the fnmatch() function),

and on reading that section it is apparent that primaries means the same as operands. That is, at each level of command-parsing, the command (or primary) has some further primaries to consider until all that are left are constants or variables: aka "operand".

  • Thanks. If you think it as an operand but not an operation/operator, how do you understand "the file argument to one of the primaries ", and "primaries that operate on files" in the quote?
    – Tim
    Jan 10, 2016 at 16:18
  • As I said: level of command-parsing. Work down from [[ (test) to -f (operator) to filename. At one level, "test" is an operator, and its primaries are the expressions it is prepared to process. Down another level, -f is an operator, and it is looking for filename. Jan 10, 2016 at 18:57

The term seems to be used ambiguously.  It seems to mean either

  • an operator, or
  • an operator, combined with one or two operands, as appropriate, to produce a Boolean value


The Bash Reference Manual, Section Conditional Constructs, talking about [[]], says,

…  Expressions are composed of the primaries described below in Bash Conditional Expressions.  …

which is the somewhat confusing section that you quote in your question.  It goes on to list -a file, -b file, …, -t fd, …, file1 -ef file2, …, -z string, …, string1 != string2, etc.

And the POSIX Specification for the test command, section OPERANDS (thanks, BinaryZebra, for identifying that source) says,

The primaries with two elements of the form:
    -primary_operator primary_operand
are known as unary primaries.  The primaries with three elements in either of the two forms:
    primary_operand -primary_operator primary_operand

    primary_operand primary_operator primary_operand
are known as binary primaries.  …

So, these two sources seem to agree that -b file, -c file, etc., are the primaries.  But, you’re right; when section 6.4 of the reference manual talks about “the file argument to one of the primaries,” it certainly seems that it is referring to the operators (e.g., -b, -c, …) as primaries.

  • In the bash manual each primary is each line inside "CONDITIONAL EXPRESSIONS", of the form "-f file" or "string1 == string2". A primary is never understood as an operator in "man bash".
    – user79743
    Jan 10, 2016 at 22:50
  • @BinaryZebra: How do you figure that?  bash(1) says "… any file argument to one of the primaries …"  If it said "… any file argument component of one of the primaries …", that would be consistent with the usage that -b file is a primary — but the existing language clearly says that -b is a primary, and file is an argument to it. Jan 11, 2016 at 1:58
  • That is your interpretation. A primary is composed of arguments, the same as saying that a command may have arguments. You may say: an argument to the command, in the same spirit as it is said an argument to the primary. I see no problem in such wording with the fact that (some) primaries are composed of two arguments, or one operator and one operand. Different words applied in different groupings.
    – user79743
    Jan 11, 2016 at 2:14

Short answer (my words):

The "word"(s) that exists inside test ([[ and ]], or [ and ]) after splitting it on spaces become primaries. Words may be (!), (-f), or values ($var). Such words are also "the arguments" if the first [ or [[ is understood as a command ("test").

After the splitting, (some) two words together. Like (-f) and ($var) are called "unary primaries". And (some) three words are called "binary primary".

But that description is not that precise in some uses and wanders a bit.

Longer answer:

The concept is quite old (from Bourne shell) and is detailed in the POSIX spec (as an example) :

The application shall ensure that all operators and elements of primaries are presented as separate arguments to the test utility.
The following primaries can be used to construct expression:

Were expression means what is inside braces: [expression].

Note that here operands and operators are both meant to be the arguments (words divided on spaces) given to the test utility.

The concept of expression is also used in man bash, for example, close to the start, search for [[ expression ]] (one form of "compound commands"):

Expressions are composed of the primaries described below under CONDITIONAL EXPRESSIONS.
Conditional operators such as -f must be unquoted to be recognized as primaries.


And finally, you could search in the POSIX spec page linked above and again here for this line (and lines following):

The primaries with two elements of the form:
-primary_operator primary_operand
are known as unary primaries.

Following lines make an attempt at defining primaries with expressions that have up to 4 arguments (words split by spaces, where I started).

There are no 4 words primaries (if ! is not counted as part of a (negated) three word primary).

That POSIX description doesn't work well on many corner cases and is the main reason to develop the built-in [[ ]].


From man bash:

  • in the Compound Commands section:

    Expressions are composed of the primaries described below under CONDITIONAL EXPRESSIONS. (1)

    Conditional operators such as -f must be unquoted to be recognized as primaries. (2)

    Expressions may be combined using the following operators [...] (goes on listing: ( ), !, && and ||) [...] The && and || operators do not evaluate expression2 if the value of expression1 is sufficient to determine the return value of the entire conditional expression. (3)


    Expressions are formed from the following unary or binary primaries. (4)

    If any file argument to one of the primaries [...] (5)

    Unless otherwise specified, primaries that operate on files [...] (6)

So this is how one can understand it:

From (1) and (4) a primary is a minimal, autonomous element of a conditional expression, such as: -a FILE, FILE1 -nt FILE2, STRING, -n STRING, STRING1 == STRING2... associated with a unitary or binary operator.

From (2) (and also (4), (5) and (6)), by extension, an operator can itselves be designated as "a primary", understanding that it comes along with the relevant operands (much the same way as "command" can designate both a builtin utility or a program, or the command line built on this utility or program along with the appropriate arguments).

And from (1) and (3) the primaries are the minimal modules that can be combined to form more complex conditional expressions such as -a FILE && FILE1 -nt FILE2 with the && (AND) operator, -n STRING || STRIN1 == STRING2 with the || (OR) operator, ! STRING with the ! (NOT) operator.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.