User Commands if(1) NAME if, test - evaluate condition(s) or make execution of actions dependent upon the evaluation of condition(s) SYNOPSIS /usr/bin/test [ _c_o_n_d_i_t_i_o_n ] _c_o_n_d_i_t_i_o_n sh if _c_o_n_d_i_t_i_o_n ; then _a_c_t_i_o_n ; fi if _c_o_n_d_i_t_i_o_n ; then _a_c_t_i_o_n ; else _a_c_t_i_o_n_2 ; fi if _c_o_n_d_i_t_i_o_n ; then _a_c_t_i_o_n ; elif _c_o_n_d_i_t_i_o_n_2 ; then _a_c_t_i_o_n_2 ; ... ; fi if _c_o_n_d_i_t_i_o_n ; then _a_c_t_i_o_n ; elif _c_o_n_d_i_t_i_o_n_2 ; then _a_c_t_i_o_n_2 ; ... ; else _a_c_t_i_o_n_3 ; fi test _c_o_n_d_i_t_i_o_n [ _c_o_n_d_i_t_i_o_n ] csh if ( _c_o_n_d_i_t_i_o_n ) then _a_c_t_i_o_n else if ( _c_o_n_d_i_t_i_o_n_2 ) then _a_c_t_i_o_n_2 else _a_c_t_i_o_n_3 endif if ( _c_o_n_d_i_t_i_o_n ) [ _a_c_t_i_o_n ] ksh if _c_o_n_d_i_t_i_o_n ; then _a_c_t_i_o_n ; fi if _c_o_n_d_i_t_i_o_n ; then _a_c_t_i_o_n ; else _a_c_t_i_o_n_2 ; fi if _c_o_n_d_i_t_i_o_n ; then _a_c_t_i_o_n ; elif _c_o_n_d_i_t_i_o_n_2 ; then _a_c_t_i_o_n_2 ; ... ; fi if _c_o_n_d_i_t_i_o_n ; then _a_c_t_i_o_n ; elif _c_o_n_d_i_t_i_o_n_2 ; then _a_c_t_i_o_n_2 ; ... ; else _a_c_t_i_o_n_3 ; fi SunOS 5.8 Last change: 13 Dec 1996 1 User Commands if(1) test _c_o_n_d_i_t_i_o_n [ _c_o_n_d_i_t_i_o_n ] DESCRIPTION /usr/bin/test The test utility evaluates the _c_o_n_d_i_t_i_o_n and indicates the result of the evaluation by its exit status. An exit status of zero indicates that the condition evaluated as true and an exit status of 1 indicates that the condition evaluated as false. In the second form of the utility, which uses [] rather than test, the square brackets must be separate arguments and _c_o_n_d_i_t_i_o_n is optional. See largefile(5) for the description of the behavior of test when encountering files greater than or equal to 2 Gbyte ( 2 **31 bytes). sh The _c_o_n_d_i_t_i_o_n following if is executed and, if it returns a 0 exit status, the _a_c_t_i_o_n following the first then is exe- cuted. Otherwise, the _c_o_n_d_i_t_i_o_n_2 following elif is executed and, if its value is 0, the _a_c_t_i_o_n_2 following the next then is executed. Failing the if and elif _c_o_n_d_i_t_i_o_ns, the else _a_c_t_i_o_n_3 is executed. If no else _a_c_t_i_o_n or then _a_c_t_i_o_n is executed, the if command returns a 0 exit status. Any number of elif ... then ... branching pairs are allowed, but only one else. test evaluates the condition _c_o_n_d_i_t_i_o_n and, if its value is true, sets exit status to 0; otherwise, a non-zero (false) exit status is set; test also sets a non-zero exit status if there are no arguments. When permissions are tested, the effective user ID of the process is used. All operators, flags, and brackets (brackets used as shown in the second SYNOPSIS line) must be separate arguments to the test command; normally these items are separated by spaces. Primitives: The following primitives are used to construct _c_o_n_d_i_t_i_o_n: -r _f_i_l_e_n_a_m_e True if _f_i_l_e_n_a_m_e exists and is readable. -w _f_i_l_e_n_a_m_e True if _f_i_l_e_n_a_m_e exists and is writable. -x _f_i_l_e_n_a_m_e SunOS 5.8 Last change: 13 Dec 1996 2 User Commands if(1) True if _f_i_l_e_n_a_m_e exists and is executable. -f _f_i_l_e_n_a_m_e True if _f_i_l_e_n_a_m_e exists and is a regular file. Alternatively, if /usr/bin/sh users specify /usr/ucb before /usr/bin in their PATH environ- ment variable, then test will return true if _f_i_l_e_n_a_m_e exists and is (not-a-directory). This is also the default for /usr/bin/csh users. -d _f_i_l_e_n_a_m_e True if _f_i_l_e_n_a_m_e exists and is a directory. -h _f_i_l_e_n_a_m_e True if _f_i_l_e_n_a_m_e exists and is a symbolic link. With all other primitives (except -L _f_i_l_e_n_a_m_e), the symbolic links are followed by default. -c _f_i_l_e_n_a_m_e True if _f_i_l_e_n_a_m_e exists and is a character spe- cial file. -b _f_i_l_e_n_a_m_e True if _f_i_l_e_n_a_m_e exists and is a block special file. -p _f_i_l_e_n_a_m_e True if _f_i_l_e_n_a_m_e exists and is a named pipe (fifo). -u _f_i_l_e_n_a_m_e True if _f_i_l_e_n_a_m_e exists and its set-user- ID bit is set. -g _f_i_l_e_n_a_m_e True if _f_i_l_e_n_a_m_e exists and its set-group- ID bit is set. -k _f_i_l_e_n_a_m_e True if _f_i_l_e_n_a_m_e exists and its sticky bit is set. -s _f_i_l_e_n_a_m_e True if _f_i_l_e_n_a_m_e exists and has a size greater than zero. -t [ _f_i_l_d_e_s ] True if the open file whose file descriptor number is _f_i_l_d_e_s (1 by default) is associated with a terminal device. -z _s_1 True if the length of string _s_1 is zero. SunOS 5.8 Last change: 13 Dec 1996 3 User Commands if(1) -n _s_1 True if the length of the string _s_1 is non-zero. _s_1 = _s_2 True if strings _s_1 and _s_2 are identical. _s_1 != _s_2 True if strings _s_1 and _s_2 are not identical. _s_1 True if _s_1 is not the null string. _n_1 -eq _n_2 True if the integers _n_1 and _n_2 are algebraically equal. _n_1 -ne _n_2 True if the integers _n_1 and _n_2 are not algebrai- cally equal. _n_1 -gt _n_2 True if the integer _n_1 is algebraically greater than the integer _n_2. _n_1 -ge _n_2 True if the integer _n_1 is algebraically greater than or equal to the integer _n_2. _n_1 -lt _n_2 True if the integer _n_1 is algebraically less than the integer _n_2. _n_1 -le _n_2 True if the integer _n_1 is algebraically less than or equal to the integer _n_2. -L _f_i_l_e_n_a_m_e True if _f_i_l_e_n_a_m_e exists and is a symbolic link. With all other primitives (except -h _f_i_l_e_n_a_m_e), the symbolic links are followed by default. Operators: These primaries may be combined with the following opera- tors: ! Unary negation operator. -a Binary _a_n_d operator. -o Binary _o_r operator (-a has higher precedence than -o). (_c_o_n_d_i_t_i_o_n) SunOS 5.8 Last change: 13 Dec 1996 4 User Commands if(1) Parentheses for grouping. Notice also that parentheses are meaningful to the shell and, therefore, must be quoted. The not-a-directory alternative to the -f option is a tran- sition aid for BSD applications and may not be supported in future releases. The -L option is a migration aid for users of other shells which have similar options and may not be supported in future releases. If you test a file you own (the -r -w or -x tests), but the permission tested does not have the _o_w_n_e_r bit set, a non- zero (false) exit status will be returned even though the file may have the group or _o_t_h_e_r bit set for that permis- sion. The correct exit status will be set if you are super- user. The = and != operators have a higher precedence than the -r through -n operators, and = and != always expect arguments; therefore, = and != cannot be used with the -r through -n operators. If more than one argument follows the -r through -n opera- tors, only the first argument is examined; the others are ignored, unless a -a or a -o is the second argument. csh With the multi-line form of if: if _c_o_n_d_i_t_i_o_n is true, the _a_c_t_i_o_n up to the first else or then is executed. Otherwise, if else if _c_o_n_d_i_t_i_o_n_2 is true, the _a_c_t_i_o_n_2 between the else if and the following else or then is executed. Otherwise, the _a_c_t_i_o_n_3 between the else and the endif is executed. The if must appear alone on its input line or after an else. Only one endif is needed, but it is required. The words else and endif must be the first nonwhite characters on a line. Any number of else if ... then ... branching pairs are allowed, but only one else. endif keywords: With the one- line form of if, there are no else, then, or if the specified _c_o_n_d_i_t_i_o_n evaluates to true, the single _a_c_t_i_o_n with arguments is executed. Vari- able substitution on _a_c_t_i_o_n happens early, at the same time it does for the rest of the if command. SunOS 5.8 Last change: 13 Dec 1996 5 User Commands if(1) _a_c_t_i_o_n must be a simple command, not a pipeline, a command list, or a parenthesized command list. Note that I/O redirection occurs even if _c_o_n_d_i_- _t_i_o_n is false, when _a_c_t_i_o_n is not executed (this is a bug). ksh The _c_o_n_d_i_t_i_o_n following if is executed and, if it returns an exit status of 0, the _a_c_t_i_o_n following the first then is executed. Otherwise, the _c_o_n_d_i_t_i_o_n_2 following elif is exe- cuted and, if its value is 0, the _a_c_t_i_o_n_2 following the next then is executed. Failing that, the else _a_c_t_i_o_n_3 is exe- cuted. If no else _a_c_t_i_o_n or then _a_c_t_i_o_n is executed, then the if command returns an exit status of 0. Any number of elif ... then ... branching pairs are allowed, but only one else. For a description of the test built-in, see the ksh(1) sec- tions Conditional Expressions and Arithmetic Evaluation as well as the (sh) Bourne shell's test built-in above. [ _c_o_n_d_i_t_i_o_n ] evaluates file attributes, string comparisons, and compound "and" or "or" _c_o_n_d_i_t_i_o_ns. OPERANDS All operators and elements of primaries must be presented as separate arguments to the test utility. The following primaries can be used to construct _c_o_n_d_i_t_i_o_n: -a _f_i_l_e True, if _f_i_l_e exists. -b _f_i_l_e True if _f_i_l_e exists and is a block special file. -c _f_i_l_e True if _f_i_l_e exists and is a character special file. -d _f_i_l_e True if _f_i_l_e exists and is a directory. -e _f_i_l_e True if _f_i_l_e exists. -f _f_i_l_e True if _f_i_l_e exists and is a regular file. -g _f_i_l_e True if _f_i_l_e exists and its set group ID flag is SunOS 5.8 Last change: 13 Dec 1996 6 User Commands if(1) set. -k _f_i_l_e True, if _f_i_l_e exists and is has its sticky bit set. -n _s_t_r_i_n_g True if the length of _s_t_r_i_n_g is non-zero. -o _o_p_t_i_o_n True, if option named _o_p_t_i_o_n is on. -p _f_i_l_e True if _f_i_l_e is a named pipe (FIFO). -r _f_i_l_e True if file exists and is readable. -s _f_i_l_e True if _f_i_l_e exists and has a size greater than zero. -t _f_i_l_e__d_e_s_c_r_i_p_t_o_r True if the file whose file descriptor number is _f_i_l_e__d_e_s_c_r_i_p_t_o_r is open and is associated with a terminal. -u _f_i_l_e True if _f_i_l_e exists and its set-user-ID flag is set. -w _f_i_l_e True if _f_i_l_e exists and is writable. True will indicate only that the write flag is on. The _f_i_l_e will not be writable on a read-only file system even if this test indicates true. -x _f_i_l_e True if _f_i_l_e exists and is executable. True will indicate only that the execute flag is on. If _f_i_l_e is a directory, true indicates that _f_i_l_e can be searched. -z _s_t_r_i_n_g True if the length of string _s_t_r_i_n_g is zero. -L _f_i_l_e True, if _f_i_l_e exists and is a symbolic link. -O _f_i_l_e True, if _f_i_l_e exists and is owned by the effec- tive user ID of this process. SunOS 5.8 Last change: 13 Dec 1996 7 User Commands if(1) -G _f_i_l_e True, if _f_i_l_e exists and its group matches the effective group ID of this process. -S _f_i_l_e True, if _f_i_l_e exists and is a socket. _f_i_l_e_1-nt _f_i_l_e_2 True, if _f_i_l_e_1 exists and is newer than _f_i_l_e_2. _f_i_l_e_1-ot _f_i_l_e_2 True, if _f_i_l_e_1 exists and is older than _f_i_l_e_2. _f_i_l_e_1-ef _f_i_l_e_2 True, if _f_i_l_e_1 and _f_i_l_e_2 exist and refer to the same file. _s_t_r_i_n_g True if the string _s_t_r_i_n_g is not the null string. _s_t_r_i_n_g = _p_a_t_t_e_r_n True, if _s_t_r_i_n_g matches _p_a_t_t_e_r_n. _s_t_r_i_n_g != _p_a_t_t_e_r_n True, if _s_t_r_i_n_g does not match _p_a_t_t_e_r_n. _s_t_r_i_n_g_1=_s_t_r_i_n_g_2 True if the strings _s_t_r_i_n_g_1 and _s_t_r_i_n_g_2 are identical. _s_t_r_i_n_g_1! =_s_t_r_i_n_g_2 True if the strings _s_t_r_i_n_g_1 and _s_t_r_i_n_g_2 are not identical. _s_t_r_i_n_g_1 < _s_t_r_i_n_g_2 True, if _s_t_r_i_n_g_1 comes before _s_t_r_i_n_g_2 based on ASCII value of their characters. _s_t_r_i_n_g_1 > _s_t_r_i_n_g_2 True, if _s_t_r_i_n_g_1 comes after _s_t_r_i_n_g_2 based on ASCII value of their characters. _n_1 -eq _n_2 True if the integers _n_1 and _n_2 are algebraically equal. _n_1 -ne _n_2" True if the integers _n_1 and _n_2 are not algebrai- cally equal. _n_1 -gt _n_2" True if the integer _n_1 is algebraically greater SunOS 5.8 Last change: 13 Dec 1996 8 User Commands if(1) than the integer _n_2. _n_1 -ge _n_2" True if the integer _n_1 is algebraically greater than or equal to the integer _n_2. _n_1 -lt _n_2" True if the integer _n_1 is algebraically less than the integer _n_2. _n_1 -le _n_2" True if the integer _n_1 is algebraically less than or equal to the integer _n_2. These primaries can be combined with the following operator: !_c_o_n_d_i_t_i_o_n True if _c_o_n_d_i_t_i_o_n is false. The primaries with two elements of the form: -_p_r_i_m_a_r_y__o_p_e_r_a_t_o_r _p_r_i_m_a_r_y__o_p_e_r_a_n_d are known as _u_n_a_r_y _p_r_i_m_a_r_i_e_s. The primaries with three ele- ments in either of the two forms: _p_r_i_m_a_r_y__o_p_e_r_a_n_d -_p_r_i_m_a_r_y__o_p_e_r_a_t_o_r _p_r_i_m_a_r_y__o_p_e_r_a_n_d _p_r_i_m_a_r_y__o_p_e_r_a_n_d _p_r_i_m_a_r_y__o_p_e_r_a_t_o_r _p_r_i_m_a_r_y__o_p_e_r_a_n_d are known as _b_i_n_a_r_y _p_r_i_m_a_r_i_e_s. The algorithm for determining the precedence of the opera- tors and the return value that will be generated is based on the number of arguments presented to test. (However, when using the [...] form, the right-bracket final argument will not be counted in this algorithm.) In the following list, $1, $2, $3 and $4 represent the argu- ments presented to test. _0 _a_r_g_u_m_e_n_t_s: Exit false (1). _1 _a_r_g_u_m_e_n_t: Exit true (0) if $1 is not null; otherwise, exit false. _2 _a_r_g_u_m_e_n_t_s: SunOS 5.8 Last change: 13 Dec 1996 9 User Commands if(1) +o If $1 is !, exit true if $2 is null, false if $2 is not null. +o If $1 is a unary primary, exit true if the unary test is true, false if the unary test is false. +o Otherwise, produce unspecified results. _3 _a_r_g_u_m_e_n_t_s: +o If $2 is a binary primary, perform the binary test of $1 and $3. +o If $1 is !, negate the two-argument test of $2 and $3. +o Otherwise, produce unspecified results. _4 _a_r_g_u_m_e_n_t_s: +o If $1 is !, negate the three-argument test of $2, $3, and $4. +o Otherwise, the results are unspecified. USAGE Scripts should be careful when dealing with user-supplied input that could be confused with primaries and operators. Unless the application writer knows all the cases that pro- duce input to the script, invocations like: test "$1" -a "$2" should be written as: test "$1" && test "$2" to avoid problems if a user supplied values such as $1 set to ! and $2 set to the null string. That is, in cases where maximal portability is of concern, replace: test expr1 -a expr2 with: SunOS 5.8 Last change: 13 Dec 1996 10 User Commands if(1) test expr1 && test expr2 and replace: test expr1 -o expr2 with: test expr1 || test expr2 but note that, in test, -a has higher precedence than -o while && and || have equal precedence in the shell. Parentheses or braces can be used in the shell command language to effect grouping. Parentheses must be escaped when using sh; for example: test \( expr1 -a expr2 \) -o expr3 This command is not always portable outside XSI-conformant systems. The following form can be used instead: ( test expr1 && test expr2 ) || test expr3 The two commands: test "$1" test ! "$1" could not be used reliably on some historical systems. Unex- pected results would occur if such a _s_t_r_i_n_g condition were used and $1 expanded to !, ( or a known unary primary. Better constructs are: test -n "$1" test -z "$1" respectively. Historical systems have also been unreliable given the com- mon construct: test "$response" = "expected string" SunOS 5.8 Last change: 13 Dec 1996 11 User Commands if(1) One of the following is a more reliable form: test "X$response" = "Xexpected string" test "expected string" = "$response" Note that the second form assumes that expected string could not be confused with any unary primary. If expected string starts with -, (, ! or even =, the first form should be used instead. Using the preceding rules without the marked exten- sions, any of the three comparison forms is reliable, given any input. (However, note that the strings are quoted in all cases.) Because the string comparison binary primaries, = and !=, have a higher precedence than any unary primary in the >4 argument case, unexpected results can occur if arguments are not properly prepared. For example, in test -d $1 -o -d $2 If $1 evaluates to a possible directory name of =, the first three arguments are considered a string comparison, which causes a syntax error when the second -d is encountered. is encountered. One of the following forms prevents this; the second is preferred: test \( -d "$1" \) -o \( -d "$2" \) test -d "$1" || test -d "$2" Also in the >4 argument case, test "$1" = "bat" -a "$2" = "ball" Syntax errors will occur if $1 evaluates to ( or !. One of the following forms prevents this; the third is preferred: test "X$1" = "Xbat" -a "X$2" = "Xball" test "$1" = "bat" && test "$2" = "ball" test "X$1" = "Xbat" && test "X$2" = "Xball" EXAMPLES In the if command examples, three conditions are tested, and if all three evaluate as true or successful, then their validities are written to the screen. The 3 tests are: +o if a variable set to 1 is greater than 0, SunOS 5.8 Last change: 13 Dec 1996 12 User Commands if(1) +o if a variable set to 2 is equal to 2, and +o if the word "root" is included in the text file /etc/passwd. /usr/bin/test Example 1: Using /usr/bin/test Perform a mkdir if a directory does not exist: test ! -d tempdir && mkdir tempdir Wait for a file to become non-readable: while test -r thefile do sleep 30 done echo'"thefile" is no longer readable' Perform a command if the argument is one of three strings (two variations): if [ "$1" = "pear" ] | | [ "$1" = "grape" ] | | [ "$1" = "apple" ] then command fi case "$1" in pear|grape|apple) command;; esac The test built-in The two forms of the test built-in follow the Bourne shell's if example. Example 2: Using the sh built-in ZERO=0 ONE=1 TWO=2 ROOT=root if [ $ONE -gt $ZERO ] [ $TWO -eq 2 ] grep $ROOT /etc/passwd >&1 > /dev/null # _d_i_s_c_a_r_d _o_u_t_p_u_t then echo "$ONE is greater than 0, $TWO equals 2, and $ROOT is a user-name SunOS 5.8 Last change: 13 Dec 1996 13 User Commands if(1) in the password file" else echo "At least one of the three test conditions is false" fi Example 3: Using the test built-in Examples of the test built-in: test `grep $ROOT /etc/passwd >&1 /dev/null` # _d_i_s_c_a_r_d _o_u_t_p_u_t echo $? # _t_e_s_t _f_o_r _s_u_c_c_e_s_s [ `grep nosuchname /etc/passwd >&1 /dev/null` ] echo $? # _t_e_s_t _f_o_r _f_a_i_l_u_r_e csh Example 4: Using the csh built-in @ ZERO = 0; @ ONE = 1; @ TWO = 2; set ROOT = root grep $ROOT /etc/passwd >&1 /dev/null # _d_i_s_c_a_r_d _o_u_t_p_u_t # $_s_t_a_t_u_s _m_u_s_t _b_e _t_e_s_t_e_d _f_o_r _i_m_m_e_d_i_a_t_e_l_y _f_o_l_l_o_w_i_n_g _g_r_e_p if ( "$status" == "0" && $ONE > $ZERO && $TWO == 2 ) then echo "$ONE is greater than 0, $TWO equals 2, and $ROOT is a user-name in the password file" endif ksh Example 5: Using the ksh built-in ZERO=0 ONE=1 TWO=$((ONE+ONE)) ROOT=root if ((ONE > ZERO)) # _a_r_i_t_h_m_e_t_i_c_a_l _c_o_m_p_a_r_i_s_o_n [[ $TWO = 2 ]] # _s_t_r_i_n_g _c_o_m_p_a_r_i_s_o_n [ `grep $ROOT /etc/passwd >&1 /dev/null` ] # _d_i_s_c_a_r_d _o_u_t_p_u_t then echo "$ONE is greater than 0, $TWO equals 2, and $ROOT is a user-name in the password file" else echo "At least one of the three test conditions is false" fi The Korn shell will also accept the syntax of both the if command and the test command of the Bourne shell. When using the brackets ([]) within if commands, you must separate both inside ends of the brackets from the inside characters with a space. SunOS 5.8 Last change: 13 Dec 1996 14 User Commands if(1) ENVIRONMENT VARIABLES See environ(5) for descriptions of the following environment variables that affect the execution of test: LC_CTYPE, LC_MESSAGES, and NLSPATH. EXIT STATUS The following exit values are returned: 0 _c_o_n_d_i_t_i_o_n evaluated to true. 1 _c_o_n_d_i_t_i_o_n evaluated to false or _c_o_n_d_i_t_i_o_n was missing. >1 An error occurred. ATTRIBUTES See attributes(5) for descriptions of the following attri- butes: ____________________________________________________________ | ATTRIBUTE TYPE | ATTRIBUTE VALUE | |______________________________|______________________________| | Availability | SUNWcsu | |______________________________|______________________________| SEE ALSO csh(1), ksh(1), sh(1), test(1B), attributes(5), environ(5), largefile(5) NOTES Both the Bourne shell, sh, and the Korn shell, ksh, can use the semicolon and the carriage return interchangeably in their syntax of the if, for, and while built-in commands. SunOS 5.8 Last change: 13 Dec 1996 15