Linux Bash Scripting Tutorial


Loops

A Loop is a iterative(repetetive) block of commands runs as long as control condition is true

Bash supports the following looping constructs

  • for
  • while
  • until

for loop

This is a basic looping constructs in bash shell. Popular looping construct, versatile syntax looping any list of values, or arrays.

for loop syntax

		for arg in [list]
		do
			command(s);
		done;
	

Here [list] of items/array of items are optional. if [list] is empty/nulls reads input from command line i.e positional parameters

for loop example:

		for i in 1 2 3 4 5
		do
			echo -n $i ' '
		done
		
		output
		1 2 3 4 5
	

For each iteration variable i contains one value from the list
here [list] is 1 2 3 4 5
1st Iteration i has value 1
2nd Iteration i has value 2 etc.,

here list items are seperated by space, see below example

IFS -Internal Field seperator by default set to space. User can set any symbol other than space.
Here IFS set to color(:) as delimiter, in above case space is the delimiter

		IFS=':'
		for i in 1:2:3:4:5
		do
			echo -n $i ' '
		done

		output
		1 2 3 4 5

	

Wild character in for loop list

     In this for loop , list has a b * c d, note: whenever loop sees wild card '*' , bash performs file expansion, similarly `ls *`. In ls * , lists all files ,sub directory files recursively. where as in for loop, displays only current directory's files and sub-directories.

		for i in a b * c d
		do
			echo -n $i ' '
		done
	

'C' langauage style - for loop syntax

		for (( expression1; condition; expression2))
		do
			command(s);
		done;
	

expression1 initial value. expression2 increment/decrement the value(s) loop iterates till condition is false

'C' langauage for loop example:

printing numbers from 1 to 10

		for (( i=1 ; i <= 10 ; i++)
		do
			echo -n $i ' '
		done
		echo
		
		output
		1 2 3 4 5 6 7 8 9 10
	

printing numbers from 10 to 1

		for (( i=10 ; i >=1  ; i--))
		do
			echo -n $i ' '
		done
		echo

		output
		10 9 8 7 6 5 4 3 2 1

	

Reverse a String using For Loop

Algorithm:
  • Read a String using Read command or mock up a Value
  • Find length of the String
  • Bash supports variable substitution, Print String value from last using -ve index
  • append using += operator
  • Loop repeates until it the reaches first character
  • Print Reversed String
#!/usr/bin/bash
#*************************************************
#     THis  Program  Reverses a String using For Loop
#*************************************************

name='Rust programming'

length=${#name}

for (( i=-1 ;  i != -(length+1) ; i--))
do
      reverse+=${name:(i):1}
done

echo "Orginal String: ${name}"
echo
echo "Reversed String: ${reverse}"

echo
	
Output:
Orginal String:Rust programming

Reversed String:gnimmargorp tsuR

find . -iname *.cpp -print0 will print null-seperated file names.recall that this helps, if the filenames have spaces in them

while loop

This construct tests for a condition on top of a loop, and keeps looping as long as that condition is true

while loop syntax:

		while [condition]
		do
			command(s)
		done[< file]
	

while loop Example:

Display numbers from 1 to 10 using while loop

	1.	i=1
	2.	while [ $i -lq 10 ]
	3.	do
	4.		echo -n $i ' '
	5.	let "i++"
	6.	done;
	7.	echo

Line 1: Variable i set to 1
Line 2: while loop condition, $i -lq 10 -lq is less than or equal to
if i value less than or equal to 10 then it enter into loop
Line 4: print value i
Line 5: increment i value by 1 using post-increment operator and using let command.
Loop repeates from Line 2 - 5 for 10 times, when i value greater than 10,means condition is false,breaks the loop

While Loop Reading a File

     Reading a File using While loop using Input redirection Operator( < ). It is possible when you combine with Read command and in any loop. Loop continues until EOF(End Of File) is encountered.

Note: Read command reads entire line or a specified fields.

$ cat stocks.txt

symbol  company         previous   today's  date
-------------------------------------------------
msft    microsoft       247.11      241.55  2014-09-15
amzn    amazon          100.79      98.49   2018-01-20
fb      facebook        113.02      114.22  2016-03-15
ko      cocacola        61.32       60.73   2020-11-15
FILE="stocks.txt"
NEW_FILE="stocks_new.txt"

:>File   truncates the file

#echo "">"$NEW_FILE"
:>"$NEW_FILE"

lc=0;
	 #read fields

while read symbol company prev today dt
do

	 #ignore header
	 let "lc = lc+1"
	 if test $lc -le 2;
	 then
	     continue;
	 fi

	 #trade gain or loss

   change=$(echo $today-$prev | bc)

	 #trade gain or loss percentage

   perct=$(echo "scale=2;$change*100/$prev" | bc)

   #write into a new file

   echo -e "${symbol^^}\t$prev\t$today\t$change\t${perct}%\t$dt">>"$NEW_FILE"

done < $FILE
$ cat stocks_new.txt

MSFT	247.11	241.55	-5.56	-2.25%	2014-09-15
AMZN	100.79	98.49	-2.30	-2.28%	2018-01-20
FB	113.02	114.22	1.20	1.06%	2016-03-15
KO	61.32	60.73	-.59	-.96%	2020-11-15

While Loop and Here Document

     Here Document represents multi-line text , it has special syntax to represent text spanned across multiple Lines

 cmd<<NAME
       some line(s)
    NAME  #Mark end of the Document
	cmd <<DOCUMENT
	   line 1
	   line 2
	   line 3
	   .
	   .
	   .
	   line N
	   DOCUMENT 

While Loop is going to read multiple Lines from Here Document

	while read line 
	do
	
	     echo $line
	     
	done <<DOCU     #Here Document Starting
	This is first line
	This is second line
	This is Third line
	This is fourth line
	DOCU #Here Document Ending

Execute the Above script. output will be

	This is first line
	This is second line
	This is Third line
	This is fourth line
Note: Above Here Doc has static text.Here document can also be build dynamically using parameter expansions/shell expansions

until loop

This construct tests for a condition on top of a loop, and keeps looping as long as that condition is false, just opposite of while loop

until loop syntax:

		until [condition-is-true]
		do
			command(s)
		done
	

until loop example:

displaying numbers from 1-10 using until loop in bash

		1.	declare -i i=1;

		2.	until  [ $i -eq 11 ] 
		3.	do
		4.		echo -n $i ' '
		5.		let "i = i+1"
		6.	done
		7.	echo

	

output:1 2 3 4 5 6 7 8 9 10

Explanation:

Line 1 : declare integer variable and initialize it with 1
Line 2 : until loop condition, if condition is false then it enters into loop executes commands, if false exits from the loop
Line 3: i equals to 1 and not equal to 11, so it enters into loop
Line 4: prints value i using echo command
Line 5: Increment value i by 1 using let arithmetic command.
repeate Line 2-5 for 10 times, in 11th iteration it matches with condition and condition is said to be true breaks the loop

Netsted Loops

Loop control

commands affecting loop behavior

break andcontinue loop control commands

break commands terminates the loop(breaks out of the loop)

continue commands causes a jump to the next iteration of the loop,skipping all remaining commands next to it.

continue command example:

print even numbers from 1 to 10

		1.	for i in {1..10}
                2.	do
                3.	        if [[ $(($i % 2)) -ne 0 ]];
                4.	        then
                5.	                continue;
                6.	        fi
                7.	        echo -n $i ' '
                8.	done
                9.	echo
	

continue command example 2:

     This example displays directory names,
d=$(file -b "$i") , file command is used to find type of the file, whether it is directory, ascii text file etc., -b option suppresses file name. "$i" $i gives file, if filename has spaces , it should be sorrounded by double quotes. if condition checks for directory ,if not continue statement executed,i.e it goes to next item in the list,(skips below statements)

	
#!/usr/bin/bash

echo "*************************************************************"
echo "This example displays directory names in a current directory"
echo "*************************************************************"

                for i in *
                do

                d=$(file -b "$i")


                if [ "$d" != "directory" ]
                then
                        continue;
                fi;

                        echo $i
                done
                      		
	

ADS