= Shell Test = <> ---- == Usage == There are two interfaces to shell tests: * `test(1)` * the alias `[` (which requires a `]` following all operands, strings, and expressions) Both are equivalent, POSIX compliant, and portable. `test(1)` sets the exit code to 0 if the test is true, and 1 if false. Shell tests are frequently used with [[Shell/Logic#Conditional_Logic|conditional logic]]. {{{ if [ TEST ]; then : fi }}} ---- == Variable Tests == || '''Usage''' || '''True if...''' || || `var1 = var2` || var1 is equivalent to var2 || || `var1 != var2` || var1 is not equivalent to var2 || || `-z var` || string length of var is 0 || || `-n var` || string length of var is not 0 || || `var1 -eq var2` || var1 is numerically equal to var2 || || `var1 -ne var2` || var1 is numerically inequal to var2 || || `var1 -gt var2` || var1 is numerically greater than var2 || || `var1 -ge var2` || var1 is numerically greater than/ equal to to var2 || || `var1 -lt var2` || var1 is numerically lesser than var2 || || `var1 -le var2` || var1 is numerically lesser than/ equal to to var2 || === Caveats and Warnings === It is absolutely critical for variables to be quoted within tests, because they are evaluated by the shell. Even so, if any variables can be set to an empty string (or unset), these tests can suffer from instability. For example, `"$var" = foo` could evaluate to `= foo`, which would raise an error since the `=` operator requires values on either side. The common workaround is prefixing with an arbitrary letter, typically "x". In summary: {{{ # bad if [ $var = foo ]; then : fi # good if [ x"$var" = "xfoo" ]; then : fi }}} ---- == File Tests == These are probably what you are looking for. || '''Usage''' || '''True if...''' || || `-d fn` || directory exists || || `-e fn` || file exists || These rarely are useful. || '''Usage''' || '''True if...''' || || `-b fn` || file exists and is a block special file || || `-c fn` || file exists and is a character special file || || `-f fn` || file exists and is a regular file || || `-g fn` || file exists and its set-group-id bit is set || || `-h fn` || '''symbolic link''' exists (same as `-L`) || || `-p fn` || '''named pipe''' (FIFO) exists || || `-r fn` || file exists and is readable || || `-s fn` || file exists and its size is greater than zero || || `-t fn` || '''file descriptor''' is open and refers to a terminal || || `-u fn` || file exists and its set-user-id bit is set || || `-w fn` || file exists and is writable || || `-x fn` || file exists and is executable || || `-L fn` || '''symbolic link''' exists (same as `-h`) || || `-S fn` || '''socket''' exists || ---- == Compound Logic == To negate a test, insert `!` before the expression. Note that negation is applied to the '''last''' test only. {{{ if [ ! TEST ]; then : fi }}} The `test(1)` command supports options for `AND` and `OR` operations (`-a` and `-o` respectively). '''Do not use these.''' The `test(1)` command also respects parentheses for ordering operations. '''Again, do not use these.''' {{{ if [ TEST -a \( TEST -o TEST \) ]; then : fi }}} Instead, consider a less ambiguous grammar construct. {{{ if [ TEST ] && [ TEST ]; then : fi if [ TEST ] || [ TEST ]; then : fi }}} ---- CategoryRicottone