The basic format:
if [ <test-commands> ] then <commands> fi
Note there is a space after the [ and before the ]
Common test commands:
Primary | Meaning |
---|---|
[ -a FILE ] | True if FILE exists. |
[ -b FILE ] | True if FILE exists and is a block-special file. |
[ -c FILE ] | True if FILE exists and is a character-special file. |
[ -d FILE ] | True if FILE exists and is a directory. |
[ -e FILE ] | True if FILE exists. |
[ -f FILE ] | True if FILE exists and is a regular file. |
[ -g FILE ] | True if FILE exists and its SGID bit is set. |
[ -h FILE ] | True if FILE exists and is a symbolic link. |
[ -k FILE ] | True if FILE exists and its sticky bit is set. |
[ -p FILE ] | True if FILE exists and is a named pipe (FIFO). |
[ -r FILE ] | True if FILE exists and is readable. |
[ -s FILE ] | True if FILE exists and has a size greater than zero. |
[ -t FD ] | True if file descriptor FD is open and refers to a terminal. |
[ -u FILE ] | True if FILE exists and its SUID (set user ID) bit is set. |
[ -w FILE ] | True if FILE exists and is writable. |
[ -x FILE ] | True if FILE exists and is executable. |
[ -O FILE ] | True if FILE exists and is owned by the effective user ID. |
[ -G FILE ] | True if FILE exists and is owned by the effective group ID. |
[ -L FILE ] | True if FILE exists and is a symbolic link. |
[ -N FILE ] | True if FILE exists and has been modified since it was last read. |
[ -S FILE ] | True if FILE exists and is a socket. |
[ FILE1 -nt FILE2 ] | True if FILE1 has been changed more recently than FILE2, or if FILE1 exists and FILE2 does not. |
[ FILE1 -ot FILE2 ] | True if FILE1 is older than FILE2, or is FILE2 exists and FILE1 does not. |
[ FILE1 -ef FILE2 ] | True if FILE1 and FILE2 refer to the same device and inode numbers. |
[ -o OPTIONNAME ] | True if shell option “OPTIONNAME” is enabled. |
[ -z STRING ] | True of the length if “STRING” is zero. |
[ -n STRING ] or [ STRING ] | True if the length of “STRING” is non-zero. |
[ STRING1 == STRING2 ] | True if the strings are equal. “=” may be used instead of “==” for strict POSIX compliance. |
[ STRING1 != STRING2 ] | True if the strings are not equal. |
[ STRING1 < STRING2 ] | True if “STRING1” sorts before “STRING2” lexicographically in the current locale. |
[ STRING1 > STRING2 ] | True if “STRING1” sorts after “STRING2” lexicographically in the current locale. |
[ ARG1 OP ARG2 ] | “OP” is one of -eq, -ne, -lt, -le, -gt or -ge. These arithmetic binary operators return true if “ARG1” is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to “ARG2”, respectively. “ARG1” and “ARG2” are integers. |
Note:
- When we refer to FILE above we are actually meaning a path. Remember that a path may be absolute or relative and may refer to a file or a directory.
- There should be a space after [ and before ]
If Else
Sometimes we want to perform a certain set of actions if a statemen is true, and another set of actions if it is false. We can accommodate this with the else mechanism.
if [ <some test> ] then <commands> else <other commands> fi
Now we could easily read from a file if it is supplied as a command line argument, else read from STDIN.
If Elif Else
Sometimes we may have a series of conditions that may lead to different paths.
if [ <some test> ] then <commands> elif [ <some test> ] then <different commands> else <other commands> fi
For example it may be the case that if you are 18 or over you may go to the party. If you aren’t but you have a letter from your parents you may go but must be back before midnight. Otherwise you cannot go.
Boolean Operations
Sometimes we only want to do something if multiple conditions are met. Other times we would like to perform the action if one of several condition is met. We can accommodate these with boolean operators.
- and – &&
- or – ||
Case Statements
Sometimes we may wish to take different paths based upon a variable matching a series of patterns. We could use a series of if and elif statements but that would soon grow to be unweildly. Fortunately there is a case statement which can make things cleaner. It’s a little hard to explain so here are some examples to illustrate:
case <variable> in <pattern 1>) <commands> ;; <pattern 2>) <other commands> ;; esac
Here is a basic example:
case.sh
#!/bin/bash
# case example
case $1 in
start)
echo starting
;;
stop)
echo stoping
;;
restart)
echo restarting
;;
*)
echo don\'t know
;;
esac
- We identify the end of this set of statements with a double semi-colon ( ;; ). Following this is the next case to consider.
- Remember that the test for each case is a pattern. The * represents any number of any character. It is essentialy a catch all if for if none of the other cases match. It is not necessary but is often used.
- esac is case backwards and indicates we are at the end of the case statement. Any other statements after this will be executed normally.
Example:
Check if a file has executable permission:
#!/bin/bash echo "enter the path of the file" read filename if [ -x $filename ] then echo "file '$filename' is executable" else echo "file '$filename' is not executable or found" fi
If you are running a Old Linux version on hyper-V server, the integration service are not available, the NIC may go down from time to time, and the only fix may be use ifdown and ifup command. With script you can monitor this and reset the NIC with crontab:
Script: /var/scripts/nic_reset.sh
if ! ping -Q 5 -c 5 8.8.8.8; then /sbin/ifdown eth0 sleep 2 /sbin/ifup eth0 fi
Then create a crontab to run this script every one minute:
sudo crontab -e
Add below line:
*/1 * * * * /var/scripts/nic_reset.sh
There will be about one minute down time, but still faster than manually reset.