# Conditional Expressions Conditionals are how your scripts make decisions: run different code based on a true/false outcome. In Bash, `[[` is your go-to for testing files, strings, and numbers. Let's start with a basic example: ```bash touch conditional_test.sh ``` Open `conditional_test.sh` and add: ```bash #!/usr/bin/env bash my_var="data" if [[ -n "$my_var" ]]; then # If variable is not empty echo "Variable contains data." fi ``` Save, make executable, and run: ```bash chmod +x conditional_test.sh ./conditional_test.sh ``` Output: `Variable contains data.` Now, for your full reference: ## File Tests These check file attributes. Use `"${file}"` to handle spaces in names. * `[[ -e "${file}" ]]` - True if `file` exists. * `[[ -f "${file}" ]]` - True if `file` exists and is a regular file. * `[[ -d "${file}" ]]` - True if `file` exists and is a directory. * `[[ -s "${file}" ]]` - True if `file` exists and is not empty (size > 0). * `[[ -r "${file}" ]]` - True if `file` exists and is readable. * `[[ -w "${file}" ]]` - True if `file` exists and is writable. * `[[ -x "${file}" ]]` - True if `file` exists and is executable. * `[[ -L "${file}" ]]` - True if `file` is a symbolic link (`-h` is also used). * `[[ -b "${file}" ]]` - True if `file` exists and is a block device. * `[[ -c "${file}" ]]` - True if `file` exists and is a character device. ## String Tests Compare string properties and values. * `[[ -v "${varname}" ]]` - True if `varname` is set (has a value). * `[[ -z "${string}" ]]` - True if `string` has zero length (empty). * `[[ -n "${string}" ]]` - True if `string` has non-zero length (not empty). * `[[ "${string1}" == "${string2}" ]]` - True if strings are equal. (`==` allows pattern matching inside `[[`.) * `[[ "${string1}" != "${string2}" ]]` - True if strings are not equal. * `[[ "${string1}" < "${string2}" ]]` - True if `string1` sorts before `string2` lexicographically. * `[[ "${string1}" > "${string2}" ]]` - True if `string1` sorts after `string2` lexicographically. ## Numeric Comparisons Compare integer values. * `[[ ${arg1} -eq ${arg2} ]]` - True if `arg1` equals `arg2`. * `[[ ${arg1} -ne ${arg2} ]]` - True if `arg1` not equals `arg2`. * `[[ ${arg1} -lt ${arg2} ]]` - True if `arg1` less than `arg2`. * `[[ ${arg1} -le ${arg2} ]]` - True if `arg1` less than or equal to `arg2`. * `[[ ${arg1} -gt ${arg2} ]]` - True if `arg1` greater than `arg2`. * `[[ ${arg1} -ge ${arg2} ]]` - True if `arg1` greater than or equal to `arg2`. ## Logical Operators Combine multiple conditions. * **AND (`&&`)**: Both conditions must be true. ```bash # Example: file exists AND is not empty if [[ -f "my_file.txt" && -s "my_file.txt" ]]; then echo "File is present and has content." fi ``` * **OR (`||`)**: At least one condition must be true. ```bash # Example: either file or directory exists if [[ -f "another_file.txt" || -d "another_dir" ]]; then echo "Found a file or a directory." fi ``` ## Exit Status Checks `$?:` The exit status of the *last* executed command. `0` means success. Any non-zero value indicates an error. * **Success:** ```bash command_to_run if [[ $? -eq 0 ]]; then echo "Command succeeded." fi ``` * **Failure:** ```bash command_to_run if [[ $? -ne 0 ]]; then echo "Command failed." fi ```