Created
June 7, 2016 20:52
-
-
Save tlewiscpp/c0d30715a1ece9a79e6ee566a28d77f1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
#Notes going forward: the "declare" statements may be | |
#unecessary, but they are included for completeness. | |
#For tests, [[ ]] is used instead of [ ] as the former allows | |
#complex boolean expressions (ie && and ||) | |
#Also, bash interprets a 0 as true and a non-zero as false | |
#WTF, indeed | |
#If the command line -d if passed when executing this shell script, | |
#Turn on shell script trace debugging. This is found using the getopts | |
#bash builtin. If SETXTRACE is null after the getopts loop, xtrace is | |
#not turned on. Otherwise, it gets turned on. The second argument to | |
#getopts are the switches it looks for. If it finds one, it sets the | |
#variable $OPTARG to the full switch. If a colon is used, getopts will | |
#look for an argument to that switch. If it does not find one, it will | |
#set arg=: and OPTARG to the option lacking an argument. If a colon is | |
#included in the front of the second argument, getopts does all of the | |
#standard error messaging for you, so don't exclude that. OPTIND is the | |
#index variable for the loop, so it gets incremented on each successive | |
#loop. Here, we just want to look for the -d switch. | |
declare -i SETXTRACE=0 | |
while getopts :d arg; do | |
case $arg | |
#When getopts finds a -* switch, it saves it in the | |
#arg variable, excluding the -. The case d|D allows the | |
#case to be triggered with either a lowercase or uppercase | |
#d is entered as the switch. The ;; ends the case | |
d|D) SETXTRACE=1 ;; | |
\?) echo "-$OPTARG is not a -d switch, ignorning" >&2 ;; | |
esac | |
done | |
echo "SETXTRACE = $SETXTRACE" | |
if [[ $SETXTRACE -eq 1 ]]; then | |
echo "Setting xtrace" | |
set -o xtrace | |
else | |
echo "No -d switch found, leaving xtrace off. Include -d in command line arguments to turn xtrace on" | |
fi | |
#The trap builtin allows the bash script to trap certain keryboard | |
#interrupts, and execute the command enclosed in the single parentheses. | |
#Using semi-colons, one can chain together several commands to be | |
#performed when the signal is caught. The default behavior | |
#for trap is to exit the script, and calling trap without any commands | |
#resets the trapped signals to the default. Signals can either be named | |
#or numerical. These are the same commands that the kill utility | |
#accepts as arguments. For a full list of the signals that can be | |
#trapped and killed, use kill -l, trap -l, or man 7 trap | |
trap 'echo "Thanks for using this example script! Goodbye."; set +o xtrace' EXIT | |
#Declare arbitrary array called 'NAMES' to hold the names | |
#tyler, bridgette, kourtney, and karla | |
declare -a NAMES=(tyler bridgette kourtney karla) | |
#Declare an integer variable to hold the number of elements in | |
#the NAMES array using a bash builtin function. Bash first expands | |
#${#NAMES[*]} to a string representation of the number of elements | |
#in the NAMES array, then bash expands $(( )) to the integer | |
#representation of the number of elements in the NAME array | |
declare -i LENGTHOFNAMES=$((${#NAMES[*]})) | |
#Declare an integer variable to hold the length of an | |
#element in the NAMES array using a bash builtin function | |
declare -i LENGTHOFMEMBER= | |
#Declare an empty array that will hold the arguments | |
declare -a ARGS= | |
#Declare integer variable to hold the number | |
#of arguments. $# expands to the string | |
#representation of the number of command line | |
#arguments, not including the script | |
#name itself. Then. the $(( )) expands the string | |
#into an integer number, which then gets assigned | |
declare -i NUMOFARGS=$(($#))+1 | |
#Declare integer variable to hold the PID of | |
#the parent shell. Same expansion as above | |
declare -i SHELLPID=$$ | |
#Declare integer variable to hold the PID | |
#of the most recent background process | |
#Not entirely useful | |
declare -i BGPID=$! | |
#Declare integer variable to hold the exit | |
#status of the previously run command | |
declare -i LASTEXIT=$? | |
#A simple way of displaying specific arguments | |
#The $0 is expanded to the first command on the | |
#command line (the name of the script), the $1 | |
#is expanded to the second command, and so on | |
echo First 5 arguments are $0 $1 $2 $3 $4 | |
#For i; implies for i in $@, which expands to all command | |
#line arguments. The shell then expands $i to the value | |
#of i at that time. | |
for i; do | |
echo -n "$i " | |
done | |
echo | |
#Display the number of arguments. The $(( )) gets expanded | |
#as above, in the number of args line | |
echo "Number of arguments = $((NUMOFARGS))" | |
#Similarly, display the process ID of the parent shell. | |
echo "PID of parent shell = $((SHELLPID))" | |
#Display the process ID of the most recent background process | |
echo "PID of most recent background process = $((BGPID))" | |
#Display the exit status of the last command run | |
echo "Exit status returned by the last process run = $((LASTEXIT))" | |
#C like for loop that iterates over the number of arguments | |
for ((i=0; i<$((NUMOFARGS)); i++)); do | |
#Using the 'test' builtin ([ ] is synonymous with test), | |
#check two integer values with the -eq flag. For integer | |
#comparisons, always use -eq, -neq, etc. For string | |
#comparisons, use =, !=, etc. | |
#If the current integer value of zero is equal to zero... | |
if [[ $((i)) -eq 0 ]]; then | |
#Set the first element in the ARGS array to the first thing | |
#that appeared on the command line (the script name) | |
ARGS[0]=${0} | |
#Otherwise... | |
else | |
#Set the ith element of the array to the ith | |
#command line argument. | |
ARGS[$((i))]=$((${i})) | |
fi | |
echo "ARGS[$((i))] = ${ARGS[$((i))]}" | |
done | |
#An easier way to store all of the arguments in an array variable is to | |
#declare it using a bash builtin, like so: | |
declare -a ALLARGS=("${#@}") | |
for i in ALLARGS; do | |
echo ${ALLARGS[$i]} | |
done | |
#Another C like for loop that iterates over the NAME array | |
#and prints out the names. It also prints the length of each name | |
for ((i=0; i<$((LENGTHOFNAMES)); i++)); do | |
#LENGTHOFFMEMBER is set to the length of the ith variable in the NAMES array. The bash | |
#buildin first expands the $((i)) to an integer representing i, then expands ${#NAMES[i]} | |
#to the length of the ith element of the NAMES array | |
LENGTHOFMEMBER=${#NAMES[$((i))]} | |
echo "NAMES[$((i))] = ${NAMES[$((i))]}" | |
echo "Length of ${NAMES[$((i))]} = $((LENGTHOFMEMBER))" | |
done | |
#Now use a bash builtin conditional to print something to | |
#standard error if this variable is null. Since it has not been | |
#declared elsewhere, it is null. Note that this is commented out | |
#because it causes bash to exit with an exit code of 1 | |
#NULLVAR = ${NULLVAR:?This script was run at $(date), and the variable NULLVAR has not been set} | |
#echo "NULLVAR = $NULLVAR" | |
#A similar command can be used as a safeguard. The following | |
#will cause bash to expand to the default value specified after | |
#the colon. However, the variable will still be null | |
echo ${NULLVAR:-"Hello, World!"} | |
echo "NULLVAR = $NULLVAR" | |
#The following does the same, but assignes the default value to | |
#NULLVAR, then bash expands it | |
echo ${NULLVAR:="Hello, World!"} | |
echo "NULLVAR = $NULLVAR" | |
#Now, move on to a do...until loop. This will ask for a password | |
#two times, then not allow the user to continue the shell script | |
#until the password is entered a third time. The password is echoed | |
#back to them each time for sake of a test, no need to lock up the terminal | |
#in an example | |
echo "Now starting do...until example" | |
#Bash builtin trap command traps certain keyboard interrupts so the user | |
#cannot send a CTRL+C or whatever to exit the script. This would be used | |
#for a real password program, so the user can't just bypass logging in | |
trap 'echo "You pressed an interrupt, but I dont care. You have to enter to password to exit! Hahaha!"' 1 2 3 18 | |
#Read with a -p switch allows the prompt within quotes to be displayed | |
#to the user. Then, after the user hits return, any typed text will be | |
#stored into the specified variable (password1 in the first case) | |
#Note that this preserves spaces | |
read -p "Password: " password1 | |
read -p "Password (again): " password2 | |
#Make sure the passwords match, using a string comparison. Until | |
#they match, continue to echo that they do not match and ask for | |
#them to be input once more. The && "$password1" && "$password2" | |
#will expand to true if the variables are not null. Therefore, the | |
#logic line checks to make sure the user didn't just hit enter 3 times | |
#to bypass the password checking altogether | |
until [[ "$password1" = "$password2" && "$password1" && "$password2" ]]; do | |
echo "The passwords do not match." | |
#stty -echo can be used to not allow echo...or something | |
#stty -echo | |
read -p "Password: " password1 | |
read -p "Password (again): " password2 | |
done | |
#Password3 is initialized as a null before using it. This way, | |
#in the comparison to come, if the user doesn't enter anything before | |
#hitting return and saving null to password1 and password2, the | |
#first comparison doesn't evaluate to true, bypassing the password altogether | |
password3= | |
#tput clear can be used to completely clear the terminal screen, | |
#but it's use is omitted here because it's annoying | |
#tput clear | |
until [ "$password3" = "$password2" ]; do | |
read -p "Enter password $password2 to continue: " password3 | |
done | |
echo "Successfully entered password!" | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment