Week 3 Notes
Combining Commands and Files
Executing Multiple Commands
command1; command2; command3;Each command will be executed one after the other.
command1 && command2command2 will be executed only if command 1 succeeds
If the return code is 0 it is true and if it is greater than 0 it is false
ls && date -Q && wc -l /etc/profilewill display the dir listing followed by error that -Q is invalid; wc is not executed.
command1 || command2command2 will not be executed if command1 succeeds
ls /blah || datewill display current date after “No such file or directory”ls || datewill display just the directory listingcommand2 is like a Plan B if command1 doesn’t succeed.
Example
ls /blah ; date ; wc -l /etc/profile ;If we use parenthesis ie
(ls /blah ; date ; wc -l /etc/profile ;)the command gets executed in a subshell and is returned back to the shell we are using.We can use
echo $BASH_SUBSHELLto return an integer which tells us at what level of execution we are.(echo $BASH_SUBSHELL)will report a value of 1(ls; (date; echo $BASH_SUBSHELL))will report a value of 2
Launching too many subshells could be expensive computationally.
File Descriptors
Every command in linux has 3 file descriptors -
stdin(0) ,stdout(1),stderr(2).stdinis a pointer to a stream that is coming from the keyboard or use inputstdoutorstderrusually points to the screen where the display or output is made.the three pointers are looking at only the stream of characters.
they can be directed to a file or a command, or the default behaviour can be left as it is.
Combining a command and a file
command > file1stdoutis redirected tofile1file1will be created if it does not existif
file1exists, its contents will be overwrittenexample :
ls -1 /usr/bin > file1- displays no output on the screen because there is no errorls -1 /blah > file1- displays an error. file1 is overwritten and is now 0 Bytes.hwinfo > hwinfo.txttrying this command in a folder where there is no w permissions will generate an error
The
catcommand tries to read from the provided file name if not given it tries to read from stdin (keyboard)cat > file1will allow you to type content. The feature could be used to create text files on the command line. You can come out using theCtrl+Doption.cat file1displays the content offile1cattakes input from the keyboard and displays it on the screen (line by line; when you press enter) - Finish by pressingCtrl+Dto signify end of file.
command >> file1contents will be appended to file1
new file1 will be created if it does not exist.
Example :
date >> file2 ; wc -l /etc/profile >> file2 ; file /usr/bin/znew >> file2 ;cat >> file1to append text to a file from command line. Come out usingCtrl+D
Redirections
combining command and file (continued ..)
(contd..)
command 2> file1redirects
stderrtofile1file1, if it exists, will be overwritten.file1will be created if it does not exist.Example
ls $HOME /blah 2> error.txt
command > file1 2> file2stdoutis redirected tofile1stderris redirected tofile2Contents of file1 and file2 will be overwritten.
The output is in one file and the errors are in another file.
Example :
ls $HOME /blah > output.txt 2> error.txtls -R /etc > output.txt 2> error.txt- permission related errors in error.txt
command < file1stdinis redirected - a command expecting input from the keyboard could take the input from a file.Example :
wc /etc/profilebehaves similar towc < /etc/profile
command > file1 2>&1command output will be redirected to
file12>indicatesstderrand that is being redirected to&1(first stream) which isstdoutcontents of
file1will be overwrittenExample :
ls $ HOME /blah > file1output alone is sent to file1. Error on screenExample :
ls $ HOME /blah > file1 2>&1output and error is sent to file1.
command1 | command2Pipestdoutoutput of command 1 is sent tostdinof command2 as inputExample
ls /usr/bin | wc -l
command1 | command2 > file1command1 and command2 are combined and the
stdoutof command2 is sent tofile1. Errors are still shown on the screen.Example
ls /usr/bin | wc -l > file1- file1 has the number of lines counted by wc
command > file1 2> /dev/null/dev/nullfile - A sink for output to be discarded. Like a “black hole”We normally don’t do anything with the
/devfolder as there are sensitive system files there.If you are confident that the script is running well and you do not want to display any error on the screen, you can redirect the
stderrto/dev/nullstderris redirected to/dev/nullExample :
ls $HOME /blah > file1 2> /dev/nullExample :
ls -R /etc > file1 2> /dev/null- file1 contains the output except errors
command1 | tee file1Used in sitiations where you want to have a copy of the output in a file as well as on the screen.
The
teecommand reads fromstdinand writes tostdoutand file/s.Example :
ls $HOME | tee file1alsols $HOME | tee file1 file2for creating multiple copiesdiff file1 file2comapares files line by lineno output if the files are identical
Example :
ls $HOME /blah | tee file1 file2 | wc -l- Hereteekeeps copy of output in a file and also sends output towc -lfor further processing.Example :
ls $HOME /blah 2> /dev/null | tee file1 file2 | wc -lto supress errors. Note location of2>is since the error is generated there.
Shell Variables - Part 1
Creation, inspection, modification, lists
Creating a variable
myvar="value string"myvarcan’t start with a number, but you can mix alphanumeric and_No space around the
="value string"is the number,string orcommand. Output of a command can be assigned to myvar by enclosing the command in back-ticks.
Exporting a variable
export myvar="value string"ormyvar="value string" ; export myvarThis makes the value of the variable available to a shell that is spawned by the current shell.
Using variable values
echo $myvarecho ${myvar}can manipulate the value of the variable by inserting some commands within the braces.
echo "${myvar}_something"
Removing a variable
unset myvarRemoving value of a variable
myvar=
Test is a variable is set
[[ -v myvar ]] ; echo $?0 : success (variable myvar is set)
1 : failure (variable myvar is not set)
[[ -z ${myvar+x} ]] ; echo $?(thexcan be any string)0 : success (variable myvar is not set)
1 : failure (variable myvar is set)
Substitute default value
If the variable
myvaris not set, use “default” as its default valueecho ${myvar:-"default"}if
myvaris set display its valueelse display “default”
Set default value
If the variable
myvaris not set then set “default” as its valueecho ${myvar:="default"}if
myvaris set display its valueelse set “default” as its value and display its new value
Reset value if variable is set
If the variable
myvaris set, then set “default” as its valueecho ${myvar:+"default"}if
myvaris set, then set “default” as its value and display the new valueelse display null
List of variable names
echo ${!H*}displays the list of names of shell variables that start with H
Length of string value
echo ${#myvar}Display length of the string value of the variable
myvarif
myvaris not set then display 0
Slice of a string value
echo ${myvar:5:4}(5 is the offset and 4 is the slice length)Display 4 characters of the string value of the variable
myvarafter skipping first 5 characters.
if the slice length is larget than the length of the string then only what is available in the string will be displayed.
the offset can also be negative. However you need to provide a space after the : to avoid confusion with the earlier usage of the
:-symbol. The offset would come from the right hand side of the string.
Remove matching pattern
echo ${myvar#pattern}- matches onceecho ${myvar##pattern}- matches maximum possibleWhatever is matching the pattern will be removed and the rest of it will be displayed on the screen.
Keep matching pattern
echo ${myvar%pattern}- matches onceecho ${myvar%%pattern}- matches maximum possible
Replace matching pattern
echo ${myvar/pattern/string}- match once and replace with stringecho ${myvar//pattern/string}- match max possible and replace with string
Replace matching pattern by location
echo ${myvar/#pattern/string}- match at begining and replace with stringecho ${myvar/%pattern/string}- match at the end and replace with string
Changing case
echo ${myvar,}- Change the first character to lower case.echo ${myvar,,}- Change all characters to lower case.echo ${myvar^}- Change first character to uppercaseecho ${myvar^^}- Change all characters to upper caseThe original value of the variable is not changed. Only the display will be modified as the trigger commands are within braces.
Restricting value types
declare -i myvar- only integers assigneddeclare -l myvar- Only lower case chars assigneddeclare -u myvar- Only upper case chars assigneddeclare -r myvar- Variable is read onlyOnce a variable is set as read only you may have to restart the bash to be able to set it
Removing restrictions
declare +i myvar- integer restriction removeddeclare +l myvar- lower case chars restriction removeddeclare +u myvar- upper case chars restriction removeddeclare +r myvar- Can’t do once it is read-only
Indexed arrays
declare -a arrDeclare
arras an indexed array
$arr[0]=”value”Set value of element with index 0 in the array
echo ${arr[0]}Value of element with index 0 in the array
echo ${#arr[@]}Number of elements in the array. The
@symbol is a wild character to run through all the elements in the array
echo ${!arr[@]}Display all indices used
echo ${arr[@]}Display values of all elements of the array
unset ‘arr[2]’Delete element with index 2 in the array
arr+=(“value”)Append an element with a value to the end of the array
Associative arrays
declare -A hashdeclare
hashas an associative array
$hash[“a”]=”value”set the value of element with index a in the array
echo ${hash[“a”]}value of element with index a in the array
echo ${#hash[@]}number of elements in the array
echo ${!hash[@]}display all indices used
echo ${hash[@]}display values of all elements of the array
unset ‘hash[“a”]’delete an element with index a in the array
Can do everything in the indexed array except append because there is nothing called the end of the array as there is no sequence for the elements of a hash
Examples
truealways returns exit code 0falsealways returns exit code 1 (Check withecho $?)To check whether a variable is present
[[ -v myvar ]] ; echo $?returns 1 if the variable is not present in the memory[[ -z ${myvar+x} ]] ; echo $?returns 0 if variable is not present and 1 if it is present.xis a string that will be used as a replacement if the variable was not present.
Use of Braces
myvar=FileNameecho $myvarecho "$myvar.txt"prints FileName.txtecho "$myvar_txt"does not print anything as the variablemyvar_txtdoes not existecho "${myvar}_txt"prints Filename_txtBraces are useful in stating clearly the name of the variable.
Can also be used outside quotes
echo ${myvar}
Does the variable we have created get passed on to the shell or any other program created within the shell
myvar=3.14 ; echo $myvarbashone more level of bashps --forestto show that we are one level belowecho $myvarnot presentUse
export myvar=3.14to ensure this variable is available to all spawned sub shells.Change value of variable within the child shell
modification of value is not reflected in the value of the variable in the parent shell
even if you do export of the variable within the child shell it will not change the value within the parent shell.
Use of back-ticks
mydate=`date`value of mydate will be output of date.mydate=`echo Sunday that is today` ; echo $mydate
Manipulations for variables within the shell environment
We would like to have echo display a default value if variable is not available
echo ${myvar:-hello}the-indicates if the value is not present what is the display valueecho ${myvar:-"myvar is not set"}Set the value if it was not set already
echo ${myvar:=hello}if absent / not set then set it to the value after=If it is present it will not change
echo ${myvar:?"myvar is not set"}displays a little more information and a debug message.bash: myvar: myvar is not setUnset the value of a variable using
unset myvarecho ${myvar:+HELLO}displays the message if the variable is present
Inspecting all the variables in the shell environment
printenvenvecho ${!H*}displays the names of variables begining with ‘H’ -!indicates names of the variables instead of value.
Counting characters
mydate=`date`stores the output of thedatecommand inmydateecho ${#mydate}prints the length of the value present in mydate.length of a non-existing variable is zero
Features of using colon : within braces {}
Extracting part of a string from the value of a particular variable.
echo ${mydate:6:10}echo ${myvar:3:3}will printdefformyvar=abcdefgie: 3 characters after the offset (position 3)
Using negative offset
echo ${myvar: -3:3}andecho ${myvar: -3:4}will printefgformyvar=abcdefgnote
-is to be preceeded with a blank to avoid confusionasking for more characters, will print just what is available
echo ${myvar: -3:2}will printefformyvar=abcdefg
Extracting a portion of the date
Output of
dateisTuesday 25 January 2022 09:10:20 PM ISTOutput of
date +"%d %B %Y"is25 January 2022if
mydate=`date`thenecho ${mydate:8:16}will also print25 January 2022
Extracting patterns from a string
myvar=filename.txt.jpgecho ${myvar#*.}minimal matching displaystxt.jpgmyvar=filename.somethingelse.jpegecho ${myvar##*.}maximal matching displaysjpegecho ${myvar%*.}displays filename.somethingelsethe
%is used to indicate what has not been matched. (minimal)
echo ${myvar%%*.}displays filenamethe
%is used to indicate what has not been matched. (maximal)
Can be combined
echo ${myvar%%.*}.${myvar##*.}to getfilename.jpeg
Replacing what has been matched
Pattern matching in Linux usually goes with a pair of forward slashes.
Convert all
etoEin a stringecho ${myvar/e/E}replaces only the first occurance ofeecho ${myvar//e/E}replaces all occurances ofe
Replace characters at the begining of a string
echo ${myvar/#f/F}replaces the occurance offin the begining of the string withF. The#indicates the begining of the string
Replace characters at the end of a string
echo ${myvar/%g/G}replaces the occurance ofgat the end of the string withG. The%indicates the end of the string.
Replace jpeg with jpg, only if it is at the end of a string
echo ${myvar/%jpeg/jpg}
Modifying and storing it in a variable
myvar1=`echo ${myvar//jpeg/jpg}`
Generic command to remove day from date
echo ${mydate#*day}
Upper case to lower case and vice-versa
echo ${mydate,}changes first character to lowercaseecho ${mydate,,}converts all characters to lowercaseecho ${mydate^}changes first character to uppercaseecho ${mydate^^}changes all characters to uppercase
Restricting values that can be assigned to shell variables using
declaredeclareis a shell builtin+to unset a restriction and-to set it (Note : counterintutuve )-afor indexed arrays (need not be ordered indexes)-Afor associative arrays (dictionaries)-ifor integers-ufor uppercase conversion on assignmentInteger restriction
declare -i mynummynum=10will assign 10 to mynummynum=hellowill assign 0 to mynum
lowercase restriciton
declare -l myvarmyvar=helloassigns hello to myvarmyvar=BELLOWconverts BELLOW to lowercase and assigns it to myvar.
removing a restriction
declare +l myvarthe value is still contained after removing the restriction but you can now store upper case characters as well
declaring a read-only variable
declare -r myvaronce a variable has been set as read only, you cannot change its value and you cannot remove the read-only restriction using
+rdeclare +r myvargives the errorbash: declare: myvar: readonly variable
Arrays
declare -a arrarr[0]=Sundayarr[1]=Mondayecho ${arr[0]}echo ${arr[1]}echo ${#arr[@]}gives number of elements in the arrayecho ${arr[@]}displays all valuesecho ${!arr[@]}displays the indices`You can have any index without filling up intermediate indices. Indices are not necessarily contiguous.
arr[100]=Fridayis also validRemoving an element from an array =
unset 'arr[100]'Appending to an array
arr+=(Tuesday)Populating an array in one go
arr=(Sunday Monday Tuesday). The indices are sequential
Associative Arrays / Hashes
declare -A hashhash[0]="Amal"hash["mm12b001"]="Charlie"echo ${!hash[@]}to get indicesecho ${hash["mm12b001"]}
File names in a shell variable
myfiles=(`ls`)echo ${myfiles[@]}