bash
DESCRIPTION
TRANSCRIPT
BASH A quick basic to advance bashing
WHAT BASH?
• It’s not a harsh attack against a person nor even a skill on an MMORPG!
• BASH means Bourne Again Shell created by Brian Fox
• Most functionalities from SH are available on BASH
SHEBANG/SHABANG
• BASH scripts always starts with “#!/bin/bash”, a hash followed by an exclamation point called bang
• SHEBANG came from the combination of haSH-BANG or SHarp-BANG
• SHEBANG tells what interpreter to run, if not specified it will try to use by default BASH
• Any executable file can be used as an interpreter
HELLO!! SAMPLE
• Create a file hello.sh
• The file extension is not required since the interpreter as provided at shebang is used
• In order to execute it, chmod the file, add the execute mode an example would be “chmod 755 hello.sh”
#!/bin/bash echo “HELLO PO!!”
HELLO!! SAMPLE
• 755 (octal) in chmod (change mode) simply means read+write+exec on owner, read+exec for both group and other users
• 4 is read, 2 is write, 1 is execute so 4+2+1 = 7
• Let’s now execute it… $ ./sample.sh NOTE: . # Current working directory .. # Parent directory ~ # Home directory
• If something goes wrong (cannot chmod) and you need to execute it just use the interpreter as the command followed by the bash script
HELLO!! SAMPLE
$ bash hello.sh $ # <command> <script>
COMMENTS
• Using # creates a comment, everything after that symbol in that specific line is not executed
• To use a # as a non comment identifier, one must escape or enclose this with double or single quotes
#!/bin/bash echo 12345 # I AM A COMMENT # I AM ANOTHER COMMENT # I AM ANOTHER ANOTHER COMMENT
REDIRECTION - FILE DESCRIPTOR
SOME GUIDE (FILE DESCRIPTOR)... 0 Means STDIN 1 Means STDOUT 2 Means STDERR
STDOUT to FILE - echo “HOGE” > foobar.txt STDERR to FILE - echos “HOGE” 2> foobar.txt STD BOTH to FILE - echo “HOGE” &> foobar.txt STDOUT to STDERR - echo “HOGE” >&2 STDERR to STDOUT - echo “HOGE” 2>&1
REDIRECTION - FILE DESCRIPTOR
• Having the ampersand before the number makes it a FILE DESCRIPTOR, applies after the direction
More on files... Overwriting Content - echo “HOGE” > foobar.txt Appending Content - echo “HOGE” >> foobar.txt
• You can also redirect a file to command as if it was an input
$ cat < foobar.txt
REDIRECTION - FILE DESCRIPTOR
• Another is redirect a file to command and redirect the command’s output to a file, a combo!!
• This example redirects the content of result.csv to grep which then filters each line for an announce string
• The final result of the redirection is not sent to stdout but to a file named result-fork.csv
$ grep "announce" < result.csv > result-fork.csv
REDIRECTION - FILE DESCRIPTOR
WHAT THE?? • cat - opens a file and send the contents to
stdout • grep - line pattern matching
PIPES
• Pipes simply pass the output of the previous command to the other succeeding command
• The output (stdout) created by the echo is passed as the param for less command TRY IT!
• This time, all files (ls -l) are filtered by their names and only the ones with 2013 are to be returned (grep “2013”)
$ echo “HEEEELLUUU” | less
$ ls -l | grep “2013”
PIPES
WHAT THE?? • ls - list files on the current directory • ls -l - list files on the current directory on long format
VARIABLE
• Declaring a variable is as simple as ...something, just create a name immediately followed by an equal sign
• There are no data types!
• The example creates a variable MY_VAR without a value, simply an empty variable
#!/bin/bash MY_VAR=
VARIABLE
• This time MY_VAR has now a value of “123”
• And now MY_VAR contains the value 123 456 789
#!/bin/bash MY_VAR=123
#!/bin/bash MY_VAR=“123 456 789”
VARIABLE
• In accessing the value of a variable, just add a DOLLAR SIGN (parameter expansion) before the variable name
• It is a good habit to enclose a variable inside quotations as sometimes it might expand and produce unwanted errors
• Using of double quotes is called “weak quoting” as variables are expanded and escapes can be used
#!/bin/bash echo “$MY_VAR”
VARIABLE
• This example will then produce an error as cat will use the -x as an option rather than part of a filename
• Take note that enclosing variables inside a pair of single quotes restricts a variable to expand so that means you don’t need to escape $ in order to use it
#!/bin/bash MY_VAR=“-x SOME.txt” cat $MY_VAR
VARIABLE
• Single quotes preserve special characters and is called “full quoting” as it literally use the characters without substitution
LOCAL VARIABLE
• If you want your variable to be only available locally (inside a function) just add the keyword local
• Use this if you do not want to alter any globally declared variable
#!/bin/bash function foo {
local BAR=SAMPLE echo $BAR
}
VARIABLE LENGTH
• In order to return the length of a variable, enclose the variable name with curly braces (parameter expansion) and add a # before the variable name
#!/bin/bash FOO=1234567890 echo ${#FOO}
PARAMETER EXPANSION
The simplest form of param expansion is by adding a dollar sign on a variable
name and this form substitutes the variable name with its value Other things can also be done, see the example!!
#!/bin/bash # Some examples echo $parameter echo ${parameter:offset} # Start from offset echo ${parameter:offset:length} # Start from offset up to length echo ${parameter,} # Lower first char echo ${parameter,,} # Lower case echo ${parameter^} # Upper first char echo ${parameter^^} # Upper case echo ${#parameter} # Length of parameter
PARAMETER EXPANSION
A variable or any other parameter inside { and } can be transformed or
manipulated to form a different value
Also having a variable enclosed inside { and } makes it safe to be concatenated with other strings
#!/bin/bash # Some examples echo ${parameter+x} # Default value if set echo ${parameter-x} # Default value if unset echo ${parameter#*/} # Remove shortest matched string from start echo ${parameter##*/} # Remove longest matched string from start echo ${parameter%/*} # Remove shortest matched string from end echo ${parameter%%/*} # Remove longest matched string from end
DELETING A VARIABLE
• Using unset deletes the variable FOO which makes echo print nothing
#!/bin/bash FOO=BAR unset FOO echo $FOO
COMMAND SUBSTITUTION / SUBSHELL • Both does the same thing except that () supports nested
executions
• It is called command substitution as the command inside the backticks and () are substituted with the output produced by the command
• Variables created inside the subshell cannot be accessed outside
#!/bin/bash (echo “HALUUU”) # Will output HALUUU `echo “HALUUU”` # Will output HALUUU
COMMAND SUBSTITUTION / SUBSHELL • Subshells are parallel processes, different process from
its parent
• This time if we want to obtain the return or stdout of a subshell we do the following
#!/bin/bash FOO=$(echo “HALUUU”) # Adding the dollar sign for expansion BAR=`echo “HALUUU”`
CONDITIONS
• Same with the other languages, it does use IF ELIF and ELSE
• The basic form of this is “if [ expression ] then statement; else statement; fi” where expression is your condition and statements are the block of codes that must be executed upon meeting the condition
if [ expression ] then statement; else statement; fi
CONDITIONS
• Notice the space between the expression and the square brackets, it is strictly required to have that
• This sample checks if 1 is really equal to 1, if true then echo “ONE”
#!/bin/bash if [ “1” = “1” ] then
echo “ONE” fi
CONDITIONS
• This time notice the use of semicolon in which its purpose is to separate statements and if you would want it to be all in one line do this:
#!/bin/bash if [ “1” = “1” ]; then
echo “ONE” fi
if [ “1” = “1” ]; then echo “ONE”; fi # See? ain’t it fabulous!
CONDITIONS
• Now with else part as what we expect will only be executed only if the expression fails
#!/bin/bash if [ “1” = “1” ]; then
echo “ONE” else
echo “NONE” fi
CONDITIONS
• Now if you’re about to use multiple related conditions you may use elif which is almost the same as if though only comes after if
#!/bin/bash if [ “1” = “1” ]; then
echo “ONE” elif [ “0” = “0” ]; then
echo “ZERO” else
echo “NONE” fi
LOOPING
• For loop in bash is almost the same as for in Python although the thing it iterates is a set of words delimited by IFS (Internal Field Separator) which is by default is a space
• This example would then iterate on the returned set of files returned by “ls” command
#!/bin/bash for i in $(ls); do
echo $i done
LOOPING
• Remember that for loop follows this format, “for variable_name in word_set; do statement; done”
• If you want to have a counter like behavior in using a for loop, you may use the “seq” command as it returns numeric values starting from the first param upto the second param if two are passed and 1 upto the 1st param if only 1 is passed.
for variable_name in word_set; do statement; done
#!/bin/bash for i in $(seq 10); do
echo $i done
LOOPING
• While loop iterates “while” the expression is true, like the one we used to
#!/bin/bash COUNTER=0 while [ $COUNTER -lt 10 ]; do
let COUNTER+=1 done
LOOPING
• Until is a bit different as it will execute the loop while the expression evaluates to false
• The example will loop until COUNTER is less than 1
#!/bin/bash COUNTER=10 until [ $COUNTER -lt 1 ]; do
let COUNTER-=1 done
LOOPING
• This example redirects the contents of the file foo.txt to the while loop being fed to “read” command
#!/bin/bash while read line; do
echo $line done < foo.txt
FUNCTIONS
• Creating a function is as simple as this, function_name() { statements }
• In invoking a function use the name of the function as shown at the last line
#!/bin/bash hello() {
echo “HELLO” } hello
FUNCTIONS
• This one shows another way of creating a function
#!/bin/bash function hello {
echo “HELLO” } hello
FUNCTIONS
• In returning values, zero means true and the others means false (false in the way you may use it)
#!/bin/bash is_hello() {
if [ “$1” = “HELLO” ]; then return 0 else return 1 fi
} if is_hello “HELLO”; then
echo “HELLO” fi
FUNCTIONS
• Return can be compared to an exit code where 0 means exited OK and other codes means exited with an error
• Return can also be accessed by “$?” variable which reads the exit status of the most recent command executed
• The variable $1 means the first parameter passed which on the if clause is the word “HELLO”
FUNCTIONS
• $1 accesses the first param, $2 the second, and so on
• If you’re curious about how many of this can you passed try executing “getconf ARG_MAX”
• Wonder how to access arguments to your bash command? It’s the same as using $1 .. $n TRY IT!! AFTER THIS
SELECT
• Select behaves like a for loop with a menu like selection
• This example will present a menu containing the HELLO and QUIT as the options
#!/bin/bash OPTIONS=“HELLO QUIT” select opt in $OPTIONS; do
if [ “$opt” = “QUIT” ]; then exit elif [ “$opt” = “HELLO” ]; then echo “HELLO” fi
done
SELECT
• To access each selection a numeric value is assigned to them making 1 as HELLO and 2 as QUIT
• It will execute until the QUIT is selected
ARRAYS
• Enclosing values separated by IFS inside parenthesis or simply just an open and close parens creates an indexed array
• Another way (explicit) to create an array without doing the assignment operation is by using the “declare” command
#!/bin/bash array=() declare -a array
ARRAYS
• Assigning values follows the format “array_name[index]=value”
• Same as a regular variable, strings should be enclosed it by quotations
#!/bin/bash array[0]=FOO array[1]=BAR array[3]=“BAZ BOO”
ARRAYS
• This one is the same as the previous example though “BAZ BOO” is indexed 2 and this time using the declare
#!/bin/bash declare -a array=(FOO BAR ‘BAZ BOO’)
ARRAYS
• Arrays like other languages are indexed from 0 to N, where N is the total count of values - 1
#!/bin/bash echo ${array[@]} # Displays the elements of the array echo ${array[*]} # Displays also the elements of the array but in one whole word echo ${#array[@]} # Displays the length of array echo ${array[0]} # Access index zero also the same as ${array} echo ${#array[3]} # Displays the char length of element under index 3
ARRAYS
• This sample creates a keyed array using the “-A” option of declare
• Assigning and accessing a value is the same as the normal usage of array
#!/bin/bash declare -A array # Create a keyed array array[FOO]=BAR echo ${array[FOO]}
ARRAYS
• In order to get all of the keys of an array, use bang !
• Now in order to iterate a keyed array, use the variable ${!BAR[@]} (like from the example) in the “in” part of a for loop then make use of the values returned as the index
#!/bin/bash BAR=(‘ONE’ ‘TWO’) # Create an array BAR=(“${BAR[@]}” “THREE” “FOUR”) # Add 2 new values BAZ=(“${BAR[@]}”) # Pass array echo ${!BAR[@]} # Echo the keys of array
HEREDOC
• EOF is the limit string and is used to determine where the HEREDOC ends
• Limit string can be a word or any set of characters
• Everything inside the HEREDOC is passed to the command “cat” which then sends it to stdout
#!/bin/bash cat <<EOF FOO BAR EOF
SHIFTING POSITIONAL PARAMETERS
• Shifts positional parameter by two making $1 and $2 be $3 (as $1) and $4 (as $2)
#!/bin/bash echo $1 echo $2 shift 2 echo $1 echo $2
EXPORTING VARIABLE TO SUBPROCESS
• Using export makes the variable FOO available to its subprocess if you’re going to create one
#!/bin/bash # main.sh export FOO=BAZ ./subprocess.sh #!/bin/bash # subprocess.sh echo $FOO
READING USER INPUT
• The “read” command reads the user input and then
assigns it to the variable my_input
• Statements inside the braces are called code block in which you can also pass the contents of a file (I/O redirection)
$ read my_input
{ read line
} < foo.txt
INTEGER EXPANSION
• Line 1 and 2 does the same thing, evaluate an arithmetic expression same as the “command”
• Line 3 shows how to assign the result of the arithmetic expression
echo $(( 1 + 1 )) # Echoes 2 echo $[ 1 + 1 ] # Echoes 2 SUM=$(( 1 + 1 ))
BRACE EXPANSION
• Brace expansion is like a set of words which then is
separated by IFS upon execution
• On the sample, cat opens the file first and second then redirects its output to third
• Last sample expands “foobar.{txt,bak}” to “foobar.txt foobar.bak” making the “mv” command rename foobar.txt to foobar.bak
$ cat {first,second} > third $ mv foobar.{txt,bak}
EXTENDED BRACE EXPANSION
• This kind of expansion is like seq though separated by
IFS and provides support for other ASCII characters (ASCII sequence) like {a..z}
$ echo {1..10}
TERNARY OPERATION
• Ever wondered if a ternary operator exists, the following example shows how to use a ternary operator
• This is a shorthand form of if 10 is less than 20 assign x with a value of 1 else 0
$ (( x = 10<20?1:0 )) $ echo $x
MANUAL
• If you ever need to know how a command works or you’ve forgotten the options, you can always consult “man” the command that executes the manual of a command
$ man let $ man grep $ man cat
MISC
STRING COMPARISON OPERATORS: “$X” = “$Y” # Both are equal “$X” != “$Y” # String are not equal “$X” \< “$Y” # $X is less than $Y “$X” \> “$Y” # $X is greater than $Y -z “$X” # $X is null or empty -n “$X” # $X is not empty
MISC
ARITHMETIC RELATIONAL OPERATORS: “$X” -lt “$Y” # Less than “$X” -gt “$Y” # Greater than “$X” -le “$Y” # Less than equal “$X” -ge “$Y” # Greater than equal “$X” -ne “$Y” # Not equal “$X” -eq “$Y” # Equal
MISC
SOME TEST OPERATORS: -e # is file exist -f # is regular file -s # is not zero size -d # is directory -z # is null or zero length -n # is not null -h # is symbolic link SAMPLE: if [ -d “/path/to/directory” ]; then
echo “HELUUU” fi
MISC
INTERNAL VARIABLES (SOME) $IFS # Internal Field Separator $PATH # Path to binaries $HOME # Home directory of the user $HOSTNAME # System hostname $FUNCNAME # Name of the current function $RANDOM # Generates a random number $BASH # Path to bash $BASH_VERSION # Version of installed bash $EDITOR # Default editor used by a script $LINENO # Contains the line number where it has been called to
MISC
SPECIAL VARIABLES (SOME) $1, $2, $3 # Positional parameters $0 # Name of the shell or shell script $? # Most recent foreground pipeline exit status $! # PID of the most recent background command $$ # PID of the current shell $# # Parameter count $@ # Parameter array representation; expands to separate words $* # Parameter IFS expansion; expands to one word $- # Current option set for the shell $_ # Most recent parameter
REFERENCES
http://javarevisited.blogspot.com/2011/06/special-bash-parameters-in-script-linux.html
http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html
http://www.tldp.org/LDP/abs/html/index.html
http://www.tldp.org/LDP/Bash-Beginners-Guide/html/
http://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
http://www.thegeekstuff.com/2010/05/unix-background-job/