Návrat na detail prednášky / Stiahnuť prednášku / Univerzita Komenského / Fakulta matematiky, fyziky a informatiky / Linux
Linux test command (linux.doc)
test command or [ expr ]
test command or [ expr ] is used to see if an expression is true, and if it is true it return zero(0), otherwise returns nonzero for false.Syntax:
test expression OR [ expression ]
Example:Following script determine whether given argument number is positive.
$ cat > ispostive |
Run it as follows$ chmod 755 ispostive
$ ispostive 55 number is positive
$ispostive -45Nothing is printed
$ispostive./ispostive: test: -gt: unary operator expected
Detailed explanation
The line, if test $1 -gt 0 , test to see if first command line argument($1) is greater than 0. If it is true(0) then test will return 0 and output will printed as 5 number is positive but for -45 argument there is no output because our condition is not true(0) (no -45 is not greater than 0) hence echo statement is skipped. And for last statement we have not supplied any argument hence error ./ispostive: test: -gt: unary operator expected, is generated by shell , to avoid such error we can test whether command line argument is supplied or not.
test or [ expr ] works with
1.Integer ( Number without decimal point)
2.File types
3.Character strings
For Mathematics, use following operator in Shell Script
Mathematical Operator in Shell Script | Meaning | Normal Arithmetical/ Mathematical Statements | But in Shell |
|
|
|
| For test statement with if command | For [ expr ] statement with if command |
-eq | is equal to | 5 == 6 | if test 5 -eq 6 | if [ 5 -eq 6 ] |
-ne | is not equal to | 5 != 6 | if test 5 -ne 6 | if [ 5 -ne 6 ] |
-lt | is less than | 5 < 6 | if test 5 -lt 6 | if [ 5 -lt 6 ] |
-le | is less than or equal to | 5 <= 6 | if test 5 -le 6 | if [ 5 -le 6 ] |
-gt | is greater than | 5 > 6 | if test 5 -gt 6 | if [ 5 -gt 6 ] |
-ge | is greater than or equal to | 5 >= 6 | if test 5 -ge 6 | if [ 5 -ge 6 ] |
NOTE: == is equal, != is not equal.
For string Comparisons use
Operator | Meaning |
string1 = string2 | string1 is equal to string2 |
string1 != string2 | string1 is NOT equal to string2 |
string1 | string1 is NOT NULL or not defined |
-n string1 | string1 is NOT NULL and does exist |
-z string1 | string1 is NULL and does exist |
Shell also test for file and directory types
Test | Meaning |
-s file | Non empty file |
-f file | Is File exist or normal file and not a directory |
-d dir | Is Directory exist and not a file |
-w file | Is writeable file |
-r file | Is read-only file |
-x file | Is file is executable |
Logical Operators
Logical operators are used to combine two or more condition at a time
Operator | Meaning |
! expression | Logical NOT |
expression1 -a expression2 | Logical AND |
expression1 -o expression2 | Logical OR |
if condition
if condition which is used for decision making in shell script, If given condition is true then command1 is executed.Syntax:
if condition
then
command1 if condition is true or if exit status
of condition is 0 (zero)
...
...
fi
Condition is defined as:
"Condition is nothing but comparison between two values."
For compression you can use test or [ expr ] statements or even exist status can be also used.
Expreession is defined as:
"An expression is nothing but combination of values, relational operator (such as >,<, <> etc) and mathematical operators (such as +, -, / etc )."
Following are all examples of expression:
5 > 2
3 + 6
3 * 65
a < b
c > 5
c > 5 + 30 -1
Type following commands (assumes you have file called foo)$ cat foo
$ echo $?
The cat command return zero(0) i.e. exit status, on successful, this can be used, in if condition as follows, Write shell script as
$ cat > showfile |
Run above script as:$ chmod 755 showfile$./showfile foo
Shell script name is showfile ($0) and foo is argument (which is $1).Then shell compare it as follows:
if cat $1 which is expanded to if cat foo.
Detailed explanation
if cat command finds foo file and if its successfully shown on screen, it means our cat command is successful and its exist status is 0 (indicates success), So our if condition is also true and hence statement echo -e "\n\nFile $1, found and successfully echoed" is proceed by shell. Now if cat command is not successful then it returns non-zero value (indicates some sort of failure) and this statement echo -e "\n\nFile $1, found and successfully echoed" is skipped by our shell.
Exercise
Write shell script as follows:
cat > trmif |
Press Ctrl + d to save$ chmod 755 trmif
Answer the following question in referance to above script:
(A) foo file exists on your disk and you give command, $ ./trmfi foo what will be output?
(B) If bar file not present on your disk and you give command, $ ./trmfi bar what will be output?
(C) And if you type $ ./trmfi What will be output?
if...else...fi
If given condition is true then command1 is executed otherwise command2 is executed.Syntax:
if condition
then
condition is zero (true - 0)
execute all commands up to else statement
else
if condition is not true then
execute all commands up to fi
fi
For e.g. Write Script as follows:
$ vi isnump_n if test $1 -gt 0 |
Try it as follows:$ chmod 755 isnump_n
$ isnump_n 55 number is positive
$ isnump_n -45 -45 number is negative
$ isnump_n./ispos_n : You must give/supply one integers
$ isnump_n 00 number is negative
Detailed explanation
First script checks whether command line argument is given or not, if not given then it print error message as "./ispos_n : You must give/supply one integers". if statement checks whether number of argument ($#) passed to script is not equal (-eq) to 0, if we passed any argument to script then this if statement is false and if no command line argument is given then this if statement is true. The echo command i.e.
echo "$0 : You must give/supply one integers"
| |
| |
1 2
1 will print Name of script
2 will print this error message
And finally statement exit 1 causes normal program termination with exit status 1 (nonzero means script is not successfully run).
The last sample run $ isnump_n 0 , gives output as "0 number is negative", because given argument is not > 0, hence condition is false and it's taken as negative number. To avoid this replace second if statement with if test $1 -ge 0.
Nested if-else-fi
You can write the entire if-else construct within either the body of the if statement of the body of an else statement. This is called the nesting of ifs.
$ vi nestedif.sh |
Run the above shell script as follows:$ chmod +x nestedif.sh
$ ./nestedif.sh1. Unix (Sun Os)
2. Linux (Red Hat)
Select you os choice [1 or 2]? 1
You Pick up Unix (Sun Os)
$ ./nestedif.sh1. Unix (Sun Os)
2. Linux (Red Hat)
Select you os choice [1 or 2]? 2
You Pick up Linux (Red Hat)
$ ./nestedif.sh1. Unix (Sun Os)
2. Linux (Red Hat)
Select you os choice [1 or 2]? 3
What you don't like Unix/Linux OS.
Note that Second if-else constuct is nested in the first else statement. If the condition in the first if statement is false the the condition in the second if statement is checked. If it is false as well the final else statement is executed.
You can use the nested ifs as follows also:Syntax:
if condition
then
if condition
then
.....
..
do this
else
....
..
do this
fi
else
...
.....
do this
fi
Multilevel if-then-else
Syntax:
if condition
then
condition is zero (true - 0)
execute all commands up to elif statement
elif condition1
then
condition1 is zero (true - 0)
execute all commands up to elif statement
elif condition2
then
condition2 is zero (true - 0)
execute all commands up to elif statement
else
None of the above condtion,condtion1,condtion2 are true (i.e.
all of the above nonzero or false)
execute all commands up to fi
fi
For multilevel if-then-else statement try the following script:
$ cat > elf |
Try above script as follows:$ chmod 755 elf
$ ./elf 1
$ ./elf -2
$ ./elf 0
$ ./elf aHere o/p for last sample run:
./elf: [: -gt: unary operator expected
./elf: [: -lt: unary operator expected
./elf: [: -eq: unary operator expected
Opps! a is not number, give number
Above program gives error for last run, here integer comparison is expected therefore error like "./elf: [: -gt: unary operator expected" occurs, but still our program notify this error to user by providing message "Opps! a is not number, give number".
for Loop
Syntax:
for { variable name } in { list }
do
execute one for each item in the list until the list is
not finished (And repeat all statement between do and done)
done
Before try to understand above syntax try the following script:
$ cat > testfor |
Run it above script as follows:$ chmod +x testfor
$ ./testfor
The for loop first creates i variable and assigned a number to i from the list of number from 1 to 5, The shell execute echo statement for each assignment of i. (This is usually know as iteration) This process will continue until all the items in the list were not finished, because of this it will repeat 5 echo statements. To make you idea more clear try following script:
$ cat > mtable |
Save above script and run it as:$ chmod 755 mtable
$ ./mtable 7
$ ./mtableFor first run, above script print multiplication table of given number where i = 1,2 ... 10 is multiply by given n (here command line argument 7) in order to produce multiplication table as
7 * 1 = 7
7 * 2 = 14
...
..
7 * 10 = 70
And for second test run, it will print message -Error - Number missing form command line argument
Syntax : ./mtable number
Use to print multiplication table for given number
This happened because we have not supplied given number for which we want multiplication table, Hence script is showing Error message, Syntax and usage of our script. This is good idea if our program takes some argument, let the user know what is use of the script and how to used the script.Note that to terminate our script we used 'exit 1' command which takes 1 as argument (1 indicates error and therefore script is terminated)
Even you can use following syntax:
Syntax:
for (( expr1; expr2; expr3 ))
do
.....
...
repeat all statements between do and
done until expr2 is TRUE
Done
In above syntax BEFORE the first iteration, expr1 is evaluated. This is usually used to initialize variables for the loop.
All the statements between do and done is executed repeatedly UNTIL the value of expr2 is TRUE.
AFTER each iteration of the loop, expr3 is evaluated. This is usually use to increment a loop counter.
$ cat > for2 |
Run the above script as follows:$ chmod +x for2
$ ./for2Welcome 0 times
Welcome 1 times
Welcome 2 times
Welcome 3 times
Welcome 4 times
Welcome 5 times
In above example, first expression (i = 0), is used to set the value variable i to zero.
Second expression is condition i.e. all statements between do and done executed as long as expression 2 (i.e continue as long as the value of variable i is less than or equel to 5) is TRUE.
Last expression i++ increments the value of i by 1 i.e. it's equivalent to i = i + 1 statement.
Nesting of for Loop
As you see the if statement can nested, similarly loop statement can be nested. You can nest the for loop. To understand the nesting of for loop see the following shell script.
$ vi nestedfor.sh |
Run the above script as follows:$ chmod +x nestedfor.sh
$ ./nestefor.sh1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
5 5 5 5 5
Here, for each value of i the inner loop is cycled through 5 times, with the varible j taking values from 1 to 5. The inner for loop terminates when the value of j exceeds 5, and the outer loop terminets when the value of i exceeds 5.
Following script is quite intresting, it prints the chess board on screen.
$ vi chessboard |
Run the above script as follows:$ chmod +x chessboard
$ ./chessboard
On my terminal above script produec the output as follows:
Above shell script cab be explained as follows:
Command(s)/Statements | Explanation |
for (( i = 1; i <= 9; i++ )) | Begin the outer loop which runs 9 times., and the outer loop terminets when the value of i exceeds 9 |
for (( j = 1 ; j <= 9; j++ )) | Begins the inner loop, for each value of i the inner loop is cycled through 9 times, with the varible j taking values from 1 to 9. The inner for loop terminates when the value of j exceeds 9. |
tot=`expr $i + $j` | See for even and odd number positions using these statements. |
if [ $tmp -eq 0 ]; then | If even number posiotion print the white colour block (using echo -e -n "\033[47m " statement); otherwise for odd postion print the black colour box (using echo -e -n "\033[40m " statement). This statements are responsible to print entier chess board on screen with alternet colours. |
done | End of inner loop |
echo -e -n "\033[40m" | Make sure its black background as we always have on our terminals. |
echo "" | Print the blank line |
done | End of outer loop and shell scripts get terminted by printing the chess board. |
EXAMPLES:
1)
echo "Can you see the following:"
for (( i=1; i<=5; i++ ))
do
for (( j=1; j<=i; j++ ))
do
echo -n "$i"
done
echo ""
done
2)
MAX_NO=0
echo -n "Enter Number between (5 to 9) : "
read MAX_NO
if ! [ $MAX_NO -ge 5 -a $MAX_NO -le 9 ] ; then
echo "I ask to enter number between 5 and 9, Okay"
exit 1
fi
clear
for (( i=1; i<=MAX_NO; i++ ))
do
for (( s=MAX_NO; s>=i; s-- ))
do
echo -n " "
done
for (( j=1; j<=i; j++ ))
do
echo -n " $i"
done
echo ""
done
for (( i=1; i<=MAX_NO; i++ ))
do
for (( s=MAX_NO; s>=i; s-- ))
do
echo -n " "
done
for (( j=1; j<=i; j++ ))
do
echo -n " ."
done
echo ""
done
echo -e "\n\n\t\t\tI hope you like it my stupidity (?)"
3)
clear
for (( i=1; i<=3; i++ ))
do
for (( j=1; j<=i; j++ ))
do
echo -n "|Linux"
done
echo "______"
done
for (( i=3; i>=1; i-- ))
do
for (( j=1; j<=i; j++ ))
do
echo -n "|Linux"
done
if [ $i -eq 3 ]; then
echo -n "______"
echo -n -e ">> Powerd Server.\n"
else
echo "~~~~~"
fi
done
while loop
Syntax:
while [ condition ]
do
command1
command2
....
done
Loop is executed as long as given condition is true. For e.g.. Above for loop program (shown in last section of for loop) can be written using while loop as:
$cat > nt1 |
Save it and try as$ chmod 755 nt1
$./nt1 7Above loop can be explained as follows:
n=$1 | Set the value of command line argument to variable n. (Here it's set to 7 ) |
i=1 | Set variable i to 1 |
while [ $i -le 10 ] | This is our loop condition, here if value of i is less than 10 then, shell execute all statements between do and done |
do | Start loop |
echo "$n * $i = `expr $i \* $n`" | Print multiplication table as |
i=`expr $i + 1` | Increment i by 1 and store result to i. ( i.e. i=i+1)Caution: If you ignore (remove) this statement than our loop become infinite loop because value of variable i always remain less than 10 and program will only output |
done | Loop stops here if i is not less than 10 i.e. condition of loop is not true. Hence |
Functions
Humans are intelligent animals. They work together to perform all of life's task, in fact most of us depend upon each other. For e.g. you rely on milkman to supply milk, or teacher to learn new technology (if computer teacher). What all this mean is you can't perform all of life's task alone. You need somebody to help you to solve specific task/problem.
The above logic also applies to computer program (shell script). When program gets complex we need to use divide and conquer technique. It means whenever programs gets complicated, we divide it into small chunks/entities which is know as function.
Function is series of instruction/commands. Function performs particular activity in shell i.e. it had specific work to do or simply say task. To define function use following syntax:Syntax:
function-name ( )
{
command1
command2
.....
...
commandN
return
}
Where function-name is name of you function, that executes series of commands. A return statement will terminate the function. Example:
Type SayHello() at $ prompt as follows$ SayHello()
{
echo "Hello $LOGNAME, Have nice computing"
return
}To execute this SayHello() function just type it name as follows:$ SayHello
Hello vivek, Have nice computing.
This way you can call function. Note that after restarting your computer you will loss this SayHello() function, since its created for current session only. To overcome this problem and to add you own function to automat some of the day today life task, add your function to /etc/bashrc file. To add function to this file you must logon as root. Following is the sample /etc/bashrc file with today() function , which is used to print formatted date. First logon as root or if you already logon with your name (your login is not root), and want to move to root account, then you can type following command , when asked for password type root (administrators) password$ su -lpassword:
Open file /etc/bashrc using vi and goto the end of file (by pressing shift+G) and type the today() function:
# vi /etc/bashrc |
Save the file and exit it, after all this modification your file may look like as follows (type command cat /etc/bashrc)
# cat /etc/bashrc # System wide functions and aliases # For some unknown reason bash refuses to inherit PS1="[\u@\h \W]\\$ " # |
To run function first completely logout by typing exit at the $ prompt (Or press CTRL + D, Note you may have to type exit (CTRL +D) twice if you login to root account by using su command) ,then login and type $ today , this way today() is available to all user in your system, If you want to add particular function to particular user then open .bashrc file in users home directory as follows:
# vi .bashrc |
Save the file and exit it, after all this modification your file may look like as follows (type command cat .bashrc)
# cat .bashrc if [ -f /etc/bashrc ]; then SayBuy() |
To run function first logout by typing exit at the $ prompt (Or press CTRL + D ) ,then logon and type $ SayBuy , this way SayBuy() is available to only in your login and not to all user in system, Use .bashrc file in your home directory to add User specific aliases and functions only.
Tip: If you want to show some message or want to perform some action when you logout, Open file .bash_logout in your home directory and add your stuff here For e.g. When ever I logout, I want to show message Buy! Then open your .bash_logout file using text editor such as vi and add statement:echo "Buy $LOGNAME, Press a key. . ."read
Save and exit from the file. Then to test this logout from your system by pressing CTRL + D (or type exit) immediately you will see message "Buy xxxxx, Press a key. . .", after pressing key you will be logout and login prompt will be shown to you. :-)
Why to write function?
- Saves lot of time.
- Avoids rewriting of same code again and again
- Program is easier to write.
- Program maintains is very easy.
SCRIPT NA OBRATENIE TEXT.SUBORU
# include <stdio.h>
# include <stdlib.h>
int main (int argc, char *argv[]) {
/*** deklaracie premennych ***/
int i, j, N;
char c, **s;
/*** testovanie spravneho poctu argumentov ***/
if (argc != 2) {
printf ("syntax: %s <strana_stvorca>\n", argv[0]);
exit (1);
}
N = atoi (argv[1]); /* konverzia argumentu na cislo */
/*** alokovanie pamate na stvorec ***/
s = malloc (N * sizeof (char*));
if (s == NULL) {
printf ("alokovanie pamate na stvorec zlyhalo (malo pamate?)\n");
exit (2);
}
for (i = 0; i < N; i++) {
s[i] = malloc (N * sizeof (char));
if (s[i] == NULL) {
printf ("alokovanie pamate na riadok stvorca zlyhalo (malo pamate?)\n");
exit (3);
}
}
/*** nacitavanie stvorca zo standardneho vstupu ***/
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++)
s[i][j] = getchar();
c = getchar(); /* nacitanie znaku novy riadok */
}
/*** vypisovanie stvorca otoceneho o 90 st. doprava na standardny vystup ***/
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++)
putchar (s[N-1 - j][i]);
putchar ('\n'); /* vypisanie znaku novy riadok */
}
/*** uvolnenie alokovanej pamate na stvorec ***/
free (s);
return 0;
}