Exercices de programmation avec l’interpréteur bash

 

Préambule : la documentation en ligne de l’interpéteur bash se trouve sous http://www.gnu.org/software/bash/manual/bashref.html

 

A-  Aperitif

 

Q.1. Ecrire un fichier shell qui prend en parametre 2 entiers et affiche la somme. S'il n'y a pas deux parametres, il faut afficher un message d'erreur.
Answer:

#!/bin/bash

 

if [ $# -ne 2 ]

then

    echo "Usage - $0   x    y"

    echo "        Where x and y are two nos for which I will print sum"

    exit 1

fi

echo "Sum of $1 and $2 is `expr $1 + $2`"

#

 

Q.2. Ecrire un script qui prend en paramètre trois entiers et qui affiche le plus grand. On affichera un message d'erreur s'il n'y pas pas trois arguments passés sur la ligne de commande.
Answer:

#!/bin/bash

#

# Algo:

#      1) START: Take three nos as n1,n2,n3.

#      2) Is n1 is greater than n2 and n3, if yes

#         print n1 is bigest no goto step 5, otherwise goto next step

#      3) Is n2 is greater than n1 and n3, if yes

#         print n2 is bigest no goto step 5, otherwise goto next step

#      4) Is n3 is greater than n1 and n2, if yes

#         print n3 is bigest no goto step 5, otherwise goto next step

#      5) END

#

#

 

    if [ $# -ne 3 ]

    then

        echo "$0: number1 number2 number3 are not given" >&2

        exit 1   

    fi

    n1=$1

    n2=$2

    n3=$3

    if [ $n1 -gt $n2 ] && [ $n1 -gt $n3 ]

    then

        echo "$n1 is Bigest number"

    elif [ $n2 -gt $n1 ] && [ $n2 -gt $n3 ]        

    then

        echo "$n2 is Bigest number"

    elif [ $n3 -gt $n1 ] && [ $n3 -gt $n2 ]        

    then

        echo "$n3 is Bigest number"

    elif [ $1 -eq $2 ] && [ $1 -eq $3 ] && [ $2 -eq $3 ]

    then

        echo "All the three numbers are equal"   

    else

        echo "I can not figure out which number is biger"   

    fi   

 

Q.3. Ecrire un script shell qui affichera 5,4,3,2,1 en utilisant une boucle while.
Answer:

#!/bin/bash

#

# Algo:

#       1) START: set value of i to 5 (since we want to

#          start from 5, if you want to start from other

#          value put that value)

#       2) Start While Loop

#       3) Chechk, Is value of i is zero, If yes goto step 5 else

#          continue with next step

#       4) print i, decement i by 1 (i.e. i=i-1 to goto zero) and

#          goto step 3

#       5) END

#

i=5

while test $i != 0

do

        echo "$i

"

        i=`expr $i - 1`

done

#

Q.4. Ecrire un script qui utilisera une instruction case pour effectuer des operations arithmétiques :
+ addition
- subtraction
x multiplication
/ division
Le nom du script doit être 'q4' et il s'utilisera comme suit :
$ ./q4 20 / 3

Vérifier également qu'il y a suffisament de paramètres sur la ligne de commande.
Answer:

#!/bin/bash

#

# Q4

#

 

if test $# = 3

then

        case $2 in

         +) let z=$1+$3;;

         -) let z=$1-$3;;

         /) let z=$1/$3;;

         x|X) let z=$1*$3;;

         *) echo Warning - $2 invalied operator, only +,-,x,/ operator allowed

            exit;;

        esac

        echo Answer is $z

else

        echo "Usage - $0   value1  operator value2"

        echo "        Where, value1 and value2 are numeric values"

        echo "               operator can be +,-,/,x (For Multiplication)"

fi

 

Q.5. Ecrire un script qui listera : current date, time, username, and current directory
Answer:

#!/bin/bash

#

# Q5

#

echo "Hello, $LOGNAME"

echo "Current date is `date`"

echo "User is `who i am`"

echo "Current direcotry `pwd`"

 

 

Q.6. Ecrire un script qui prend en paramètre un entier et affiche l'entier en ordre inverse (123 -> 321).
Answer:

#!/bin/bash

#

#

# Script to reverse given no

#

# Algo:

#       1) Input number n

#       2) Set rev=0, sd=0

#       3) Find single digit in sd as n % 10 it will give (left most #          digit)

#       4) Construct revrse no as rev * 10 + sd

#       5) Decrment n by 1

#       6) Is n is greater than zero, if yes goto step 3, otherwise next step

#       7) Print rev

#

if [ $# -ne 1 ]

then

    echo "Usage: $0   number"

    echo "       I will find reverse of given number"

    echo "       For eg. $0 123, I will print 321"

    exit 1

fi

 

n=$1

rev=0

sd=0

 

while [ $n -gt 0 ]

do

    sd=`expr $n % 10`

    rev=`expr $rev \* 10  + $sd`

    n=`expr $n / 10`

done

    echo  "Reverse number is $rev"

 

Q.7. Ecrire un script qui prend en paramètre un entier et affiche la somme des digits qui le compose (123 -> 1+2+3 = 6).
Answer:

#!/bin/bash

#

#

# Algo:

#       1) Input number n

#       2) Set sum=0, sd=0

#       3) Find single digit in sd as n % 10 it will give (left most #          digit)

#       4) Construct sum no as sum=sum+sd

#       5) Decrment n by 1

#       6) Is n is greater than zero, if yes goto step 3, otherwise

#          next step

#       7) Print sum

#

if [ $# -ne 1 ]

then

    echo "Usage: $0   number"

    echo "       I will find sum of all digit for given number"

    echo "       For eg. $0 123, I will print 6 as sum of all digit (1+2+3)"

    exit 1

fi

 

n=$1

sum=0

sd=0

while [ $n -gt 0 ]

do

    sd=`expr $n % 10`

    sum=`expr $sum + $sd`

    n=`expr $n / 10`

done

    echo  "Sum of digit for numner is $sum"

   

Q.8. Quelle commande Unix vous permet de réaliser de l'arithmétique sur les réels .
Answer: Use Linux's bc command

 

Q.9. Comment calculer  5.12 + 2.5 à partir du prompt Linux ?
Answer: Use command as , $ echo 5.12 + 2.5 | bc , here we are giving echo commands output to bc to calculate the 5.12 + 2.5

 

Q.10. Comment réaliser dans un shell un calcul sur les réels ?Par exemple, on veut a=5.66, b=8.67, c=a+b.
Answer:

#!/bin/bash

#

# Q10

#

a=5.66

b=8.67

c=`echo $a + $b | bc`

echo "$a + $b = $c"

Q.11. Ecrire un script qui détermine si un fichier donné en paramètre existe.
Answer:

#!/bin/bash

#

# Q11

 

if [ $# -ne 1 ]

then

    echo "Usage - $0  file-name"

    exit 1

fi

 

if [ -f $1 ]

then

    echo "$1 file exist"

else

    echo "Sorry, $1 file does not exist"

fi

 

Q.12. Ecrire un script qui détrmine si l'argument $1 contient le symbole "*". Si $1 ne contient pas le symbole "*" ajoutez le à $1, sinon afficher le message "Symbol is not required". Le script se lance par :
$ Q12 /bin
Ici $1 est /bin, et puisque l'on n'a pas de "*" on affichera

/bin/*
Answer:

Cette version peut NE PAS marcher sur certains systèmes :

cerin@taipei:~$ /bin/bash q12.sh /bin/*

Required i.e. /bin/arch/*

cerin@taipei:~$ /bin/bash q12.sh /bin

Required i.e. /bin/*

cerin@taipei:~$


#!/bin/bash

#

# Q12

# Script to check whether "/*" is included, in $1 or not

#

 

cat "$1" > /tmp/file.$$   2>/tmp/file0.$$

 

grep "*"  /tmp/file.$$    >/tmp/file0.$$

 

if [ $? -eq 1 ]

then

    echo "Required i.e. $1/*"

else

    echo "Symbol is Not required"    

fi   

 

rm -f /tmp/file.$$

rm -f /tmp/file0.$$


Q.13. Ecrire un script qui affiche le contenu d'un fichier d'une ligne donnée à une autre. Si le script s'appelle Q13 :
$ Q13 5 5 myf , affiche le contenu du fichier myf de la ligne 5 a la ligne 9.
Answer:

#!/bin/bash

#

# Q13

#

# Shell script to print contains of file from given line no to next

# given  numberlines

#

 

#

# Print error / diagnostic for user if no arg's given

#

if [ $# -eq 0 ]

then

    echo "$0:Error command arguments missing!"

    echo "Usage: $0 start_line   uptoline   filename"

    echo "Where start_line is line number from which you would like to print file"

    echo "uptoline is line number upto which would like to print"

    echo "For eg. $0 5 5 myfile"

    echo "Here from myfile total 5 lines printed starting from line no. 5 to"

    echo "line no 10."

    exit 1

fi

 

#

# Look for sufficent arg's

#

 

    if [ $# -eq 3 ]; then

        if [ -e $3 ]; then

            tail +$1 $3 | head -n$2

         else

            echo "$0: Error opening file $3"

            exit 2

        fi  

    else

        echo "Missing arguments!"      

    fi

 

Q.14. Ecrire un script qui implémente la commande getopts. Si le script s'appelle Q14 alors on pourra lancer :
Q14 -c -d -m -e
Where options work as
-c clear the screen
-d show list of files in current working directory
-m start mc (midnight commander shell) , if installed
-e { editor } start this { editor } if installed
Answer:

#!/bin/bash

#

# Q14

# -c clear

# -d dir

# -m mc

# -e vi { editor }

#

 

#

# Function to clear the screen

#

cls()

{

    clear

    echo "Clear screen, press a key . . ."

    read

    return

}

 

#

# Function to show files in current directory

#

show_ls()

{  

    ls

    echo "list files, press a key . . ."

    read

    return

}

 

#

# Function to start mc

#

start_mc()

{

    if which mc > /dev/null ; then

        mc

        echo "Midnight commander, Press a key . . ."

        read

    else

        echo "Error: Midnight commander not installed, Press a key . . ."

        read

    fi         

    return

}

 

#

# Function to start editor

#

start_ed()

{

    ced=$1

    if which $ced > /dev/null ; then

        $ced

        echo "$ced, Press a key . . ."

        read

    else

        echo "Error: $ced is not installed or no such editor exist, Press a key . . ."

        read

 

    fi         

    return

}

 

#

# Function to print help

#

print_help_uu()

{

           echo "Usage: $0 -c -d -m -v {editor name}";

           echo "Where -c clear the screen";

           echo "      -d show dir";

           echo "      -m start midnight commander shell";

           echo "      -e {editor}, start {editor} of your choice";

           return

}

 

#

# Main procedure start here

#

# Check for sufficent args

#

 

if [ $# -eq 0 ] ; then

    print_help_uu

    exit 1

fi   

 

#

# Now parse command line arguments

#

while getopts cdme: opt

do

    case "$opt" in

        c) cls;;

        d) show_ls;;

        m) start_mc;;

        e) thised="$OPTARG"; start_ed $thised ;;

        \?) print_help_uu; exit 1;;

    esac

done              

 

Q.15. Ecrire un script que vous insérerez dans votre fichier .bash_profile. Il affichera :
Good Morning
Good Afternoon
Good Evening , selon l'heure
Answer:

#!/bin/bash

#

#

# Q15

#

 

temph=`date | cut -c12-13`

dat=`date +"%A %d in %B of %Y (%r)"`

 

if [ $temph -lt 12 ]

then

    mess="Good Morning $LOGNAME, Have nice day!"

fi

 

if [ $temph -gt 12 -a $temph -le 16 ]

then

    mess="Good Afternoon $LOGNAME"

fi

 

if [ $temph -gt 16 -a $temph -le 18 ]

then

    mess="Good Evening $LOGNAME"

fi

 

if which dialog > /dev/null

then

    dialog --backtitle "Linux Shell Script Tutorial"\

    --title "(-: Welcome to Linux :-)"\

    --infobox "\n$mess\nThis is $dat" 6 60

    echo -n "                            Press a key to continue. . .                        "

    read

    clear

else

    echo -e "$mess\nThis is $dat"

fi

 

Q.16. Ecrire un script qui affichera le message "Hello World", en gras et clignotant et dans différentes coleurs en utilisant la commande echo.
Answer:

#!/bin/bash

#

# Q16

# echo command with escape sequance to give differnt effects

#

# Syntax: echo -e "escape-code your message, var1, var2 etc"

# For eg. echo -e "\033[1m  Hello World"

#                   |         |

#                   |         |

#               Escape code   Message

#

 

clear

echo -e "\033[1m Hello World"

 # bold effect

echo -e "\033[5m Blink"

       # blink effect

echo -e "\033[0m Hello World"

 # back to noraml

 

echo -e "\033[31m Hello World"

 # Red color

echo -e "\033[32m Hello World"

 # Green color

echo -e "\033[33m Hello World"

 # See remaing on screen

echo -e "\033[34m Hello World"

echo -e "\033[35m Hello World"

echo -e "\033[36m Hello World"

 

echo -e -n "\033[0m "

  # back to noraml

 

echo -e "\033[41m Hello World"

echo -e "\033[42m Hello World"

echo -e "\033[43m Hello World"

echo -e "\033[44m Hello World"

echo -e "\033[45m Hello World"

echo -e "\033[46m Hello World"

 

 

echo -e "\033[0m Hello World"

  # back to noraml

#

Q.17. Ecrire un script qui implémente un processus en arrière plan qui affichera continuellement l'heure courante.
Answer:

#!/bin/bash

#

# Q17

# To run type at $ promot as

# $ q17 &

#

 

echo

echo "Digital Clock for Linux"

echo "To stop this clock use command kill pid, see above for pid"

echo "Press a key to continue. . ."

 

while :

do

    ti=`date +"%r"`     

    echo -e -n "\033[7s"    #save current screen postion & attributes

    #

    # Show the clock

    #

   

    tput cup 0 69     # row 0 and column 69 is used to show clock

   

    echo -n $ti       # put clock on screen

    

    echo -e -n "\033[8u" #restore current screen postion & attributs

    #

    #Delay fro 1 second

    #

    sleep 1

done

 

Q.18. Ecrire un script qui simule un menu permettant de réaliser les actions suivantes :

 

Menu-Item

Purpose

Action for Menu-Item

Date/time 

To see current date time

Date and time must be shown using infobox of dialog utility

Calendar

To see current calendar

Calendar must be shown using infobox of dialog utility

Delete

To delete selected file

First ask user name of directory where all files are present, if no name of directory given assumes current directory, then show all files only of that directory, Files must be shown on screen using menus of dialog utility, let the user select the file, then ask the confirmation to user whether he/she wants to delete selected file, if answer is yes then delete the file , report  errors if any while deleting file to user.

Exit

To Exit this shell script

Exit/Stops the menu driven program i.e. this script


Answer:

#!/bin/bash

#

 

show_datetime()

{

   dialog --backtitle "Linux Shell Tutorial" --title "System date and Time" --infobox "Date is `date`" 3 40

   read

   return

}

 

show_cal()

{

   cal > menuchoice.temp.$$

   dialog --backtitle "Linux Shell Tutorial" --title "Calender" --infobox "`cat menuchoice.temp.$$`" 9 25

   read

   rm -f menuchoice.temp.$$

   return

}

 

delete_file()

{

 dialog --backtitle "Linux Shell Tutorial" --title "Delete file"\

 --inputbox "Enter directory path (Enter for Current Directory)"\

 10 40  2>/tmp/dirip.$$

 rtval=$?

 

 case $rtval in

     1) rm -f /tmp/dirip.$$ ; return ;;

     255) rm -f /tmp/dirip.$$ ; return ;;

 esac

 

 mfile=`cat /tmp/dirip.$$`

 

 if [ -z $mfile ]

 then

     mfile=`pwd`/*

 else

     grep "*" /tmp/dirip.$$

     if [ $? -eq 1 ]

     then

        mfile=$mfile/*

     fi   

 fi

 

 for i in $mfile

 do

    if [ -f $i ]

    then

        echo "$i Delete?" >> /tmp/finallist.$$

    fi 

 done   

 

 

 dialog --backtitle "Linux Shell Tutorial" --title "Select File to Delete"\

 --menu "Use [Up][Down] to move, [Enter] to select file"\

 20 60 12 `cat /tmp/finallist.$$` 2>/tmp/file2delete.tmp.$$

 

 rtval=$?

 

 file2erase=`cat /tmp/file2delete.tmp.$$`

 

 case $rtval in

     0) dialog --backtitle "Linux Shell Tutorial" --title "Are you shur"\

      --yesno "\n\nDo you want to delete : $file2erase " 10 60

     

        if [ $? -eq 0 ] ; then

          rm -f  $file2erase        

         if [ $? -eq 0 ] ; then

            dialog --backtitle "Linux Shell Tutorial"\

            --title "Information: Delete Command" --infobox "File: $file2erase is Sucessfully deleted,Press a key" 5 60

            read

           else

            dialog --backtitle "Linux Shell Tutorial"\

            --title "Error: Delete Command" --infobox "Error deleting File: $file2erase, Press a key" 5 60

            read      

           fi

        else

          dialog --backtitle "Linux Shell Tutorial"\

          --title "Information: Delete Command" --infobox "File: $file2erase is not deleted, Action is canceled, Press a key" 5 60

          read

        fi

     ;;

    1)  rm -f /tmp/dirip.$$ ; rm -f /tmp/finallist.$$ ;

        rm -f /tmp/file2delete.tmp.$$; return;;

    255) rm -f /tmp/dirip.$$ ;  rm -f /tmp/finallist.$$ ;

         rm -f /tmp/file2delete.tmp.$$; return;;

esac

 rm -f /tmp/dirip.$$

 rm -f /tmp/finallist.$$

 rm -f /tmp/file2delete.tmp.$$

 return

}

 

 

 

while true

do

dialog --clear --title "Main Menu" \

        --menu "To move [UP/DOWN] arrow keys \n\

[Enter] to Select\n\

        Choose the Service you like:" 20 51 4 \

        "Date/time"       "To see System Date & Time" \

        "Calender"        "To see Calaender"\

        "Delete"          "To remove file"\

        "Exit"            "To exit this Program" 2> menuchoice.temp.$$

 

retopt=$?

 

choice=`cat menuchoice.temp.$$`

 

rm -f menuchoice.temp.$$

 

case $retopt in

    0)

        case $choice in

            Date/time) show_datetime ;;

            Calender) show_cal ;;

            Delete) delete_file ;;

            Exit) exit 0;;

        esac   

      ;;       

     1) exit ;;

     255) exit ;;

 esac

done

clear

Q.19. Ecrire un script qui vous permet d'afficher différentes informations sur le système :
1) Currently logged user and his logname
2) Your current shell
3) Your home directory
4) Your operating system type
5) Your current path setting
6) Your current working directory
7) Show Currently logged number of users
8) About your os and version ,release number , kernel version
9) Show all available shells
10) Show mouse settings
11) Show computer cpu information like processor type, speed etc
12) Show memory information
13) Show hard disk information like size of hard-disk, cache memory, model etc
14) File system (Mounted)

Answer:

#!/bin/bash

#

# Q19

#

 

nouser=`who | wc -l`

echo -e "User name: $USER (Login name: $LOGNAME)" >> /tmp/info.tmp.01.$$$

echo -e "Current Shell: $SHELL"  >> /tmp/info.tmp.01.$$$

echo -e "Home Directory: $HOME" >> /tmp/info.tmp.01.$$$

echo -e "Your O/s Type: $OSTYPE" >> /tmp/info.tmp.01.$$$

echo -e "PATH: $PATH" >> /tmp/info.tmp.01.$$$

echo -e "Current directory: `pwd`" >> /tmp/info.tmp.01.$$$

echo -e "Currently Logged: $nouser user(s)" >> /tmp/info.tmp.01.$$$

 

if [ -f /etc/redhat-release ]

then

    echo -e "OS: `cat /etc/redhat-release`" >> /tmp/info.tmp.01.$$$

fi

 

if [ -f /etc/shells ]

then

    echo -e "Available Shells: " >> /tmp/info.tmp.01.$$$

    echo -e "`cat /etc/shells`"  >> /tmp/info.tmp.01.$$$

fi

   

if [ -f /etc/sysconfig/mouse ]

then

    echo -e "--------------------------------------------------------------------" >> /tmp/info.tmp.01.$$$

    echo -e "Computer Mouse Information: " >> /tmp/info.tmp.01.$$$

    echo -e "--------------------------------------------------------------------" >> /tmp/info.tmp.01.$$$

    echo -e "`cat /etc/sysconfig/mouse`" >> /tmp/info.tmp.01.$$$

fi

echo -e "--------------------------------------------------------------------" >> /tmp/info.tmp.01.$$$

echo -e "Computer CPU Information:" >> /tmp/info.tmp.01.$$$

echo -e "--------------------------------------------------------------------" >> /tmp/info.tmp.01.$$$

cat /proc/cpuinfo >> /tmp/info.tmp.01.$$$

 

echo -e "--------------------------------------------------------------------" >> /tmp/info.tmp.01.$$$

echo -e "Computer Memory Information:" >> /tmp/info.tmp.01.$$$

echo -e "--------------------------------------------------------------------" >> /tmp/info.tmp.01.$$$

cat /proc/meminfo >> /tmp/info.tmp.01.$$$

 

if [ -d /proc/ide/hda ]

then

    echo -e "--------------------------------------------------------------------" >> /tmp/info.tmp.01.$$$

    echo -e "Hard disk information:" >> /tmp/info.tmp.01.$$$

    echo -e "--------------------------------------------------------------------" >> /tmp/info.tmp.01.$$$

    echo -e "Model: `cat /proc/ide/hda/model` " >> /tmp/info.tmp.01.$$$   

    echo -e "Driver: `cat /proc/ide/hda/driver` " >> /tmp/info.tmp.01.$$$   

    echo -e "Cache size: `cat /proc/ide/hda/cache` " >> /tmp/info.tmp.01.$$$   

fi

echo -e "--------------------------------------------------------------------" >> /tmp/info.tmp.01.$$$

echo -e "File System (Mount):" >> /tmp/info.tmp.01.$$$

echo -e "--------------------------------------------------------------------" >> /tmp/info.tmp.01.$$$

cat /proc/mounts >> /tmp/info.tmp.01.$$$

 

if which dialog > /dev/null

then

    dialog  --backtitle "Linux Software Diagnostics (LSD) Shell Script Ver.1.0" --title "Press Up/Down Keys to move" --textbox  /tmp/info.tmp.01.$$$ 21 70

else

    cat /tmp/info.tmp.01.$$$ |more

fi

 

rm -f /tmp/info.tmp.01.$$$

Q.20.Ecrire un script vous permettant de réaliser à l'écran le dessin suivant :

 

Ordinateur-de-Christophe-Cerin:~ cerin$ /bin/bash Q20.sh

Enter Number between (5 to 9) : 9

 

          .

         . .

        . . .

       . . . .

      . . . . .

     . . . . . .

    . . . . . . .

   . . . . . . . .

  . . . . . . . . .

  . . . . . . . . .

   . . . . . . . .

    . . . . . . .

     . . . . . .

      . . . . .

       . . . .

        . . .

         . .

          .

Ordinateur-de-Christophe-Cerin:~ cerin$

 

 

#!/bin/bash

 

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 " ."

    done

    echo ""

done

###### Second stage ######################

##

##

for (( i=MAX_NO; i>=1; i-- ))

do

    for (( s=i; s<=MAX_NO; s++ ))

    do

       echo -n " "

    done

    for (( j=1; j<=i;  j++ ))

    do

     echo -n " ."

    done

    echo ""

done

 

 

Q.21. Ecrire un script qui converti un fichier de majuscule à minuscule et vice et versa selon ce que l'on passe sur la ligne de commande.

 

Q.22 Editer un fichier pour qu’il contienne le texte suivant :

 

case $# in

    0) variable=`pwd`;;

    1) variable=$1 ;;

    *) echo "Erreur de syntaxe" ; exit;;

esac

 

a) Exécuter le code pour faire apparaitre le message d’erreur

b) Modifier le code en ajoutant du texte après le esac pour que le programme affiche la valeur de variable si elle a été positionée par `pwd`uniquement.

 

Q-23 La commande set sert a affecter les variables $0, $1 alors que la commande shift permet de décaler sur la gauche les valeurs des parametres positionnels. Voir l’exemple suivant :

 

$ set ab cd

$ echo $1

ab

$ shift

$ echo $1

cd

$ shift

$ echo $1

 

$

 

Écrire un script permettant d'afficher à l'écran le contenu d'une série de fichiers dont les noms sont passés en paramètres, et n'utilisant pas de boucle for. Le message <nom fichier> inaccessible sera affiché si le fichier <nom fichier> est inexistant ou ne peut être lu.

 

Q-24 Écrire un script (en utilisant set, par exemple) permettant de convertir une date, renvoyée par la commande date, sous le format suivant (en français) :

 

Lundi 16 Decembre 1996 15:31:37

 

Note : on peut se servir de set et shift mais on ne peut pas faire quelque chose du genre :

 

$ date "+DATE: %m/%d/%y%nTIME: %H:%M:%S"

DATE: 10/03/05

TIME: 09:53:14

 

Q-25 Tapez sous le prompt de l’interpréteur bash les commandes suivantes et observez les résultats (certains peuvent être différents sur votre système, en particulier pour la commande pwd). En fait, les () permettent d’ouvrir et de fermer un nouveau shell. Expliquer ce qui s’est passé

 

$ pwd

/users/linfg/linfg0

$ a=1

$ ( echo $a ; a=2 ; echo $a ; cd /usr/include ; pwd )

1

2

/usr/include

$ echo $a

1

$ pwd

/users/linfg/linfg0

$

 

Q-26 Taper le code suivant et observer les valeurs de a. Si vous n’obtenez pas 1 pour le premier affichage, que faut-il faire ? (voir la commande export)

$ a=1

$ bash

$ echo $a ; a=2 ; echo $a ; cd /usr/include ; pwd

$ exit

 

Q-27 Modifier le moins possible le code suivant pour faire apparaitre à l’écran que le chien et le chat sont des « animaux dosmestiques qui vivent à la maison » :

 

echo -n "Enter the name of an animal: "

read ANIMAL

echo -n "The $ANIMAL has "

case $ANIMAL in

  horse | dog | cat) echo -n "four";;

  man | kangaroo ) echo -n "two";;

  *) echo -n "an unknown number of";;

esac

echo " legs."

 

Q-28 La commande shell select permet d’élaborer facilement des menus. Taper le code suivant puis entrer un entier :

 

select fname in *;

do

        echo you picked $fname \($REPLY\)

        break;

done

 

Inspirer vous de ce texte pour ne lister que les fichiers d’extension txt ou doc. Vous pouvez utiliser l’expansion avec {}.

 

Q-29 Vous lancer la commande ps et vous la redirigez dans un fichier. Ecrire un script permettant d'afficher uniquement les processus triés par ordre alphabétique. Vous pouvez utiliser sort, uniq, cut... Modifiez votre script pour afficher le nom des processus ainsi que le nombre d'occurence de ce processus.

 

Q-30 Créer un script test-fichier, qui précisera le type du fichier passé en paramètre, ses permissions d'accès pour l'utilisateur

Exemple de résultats :

Le fichier /etc est un répertoire

"/etc" est accessible par root en lecture écriture exécution

 

Le fichier /etc/smb.conf est un fichier ordinaire qui n'est pas vide

"/etc/smb.conf" est accessible par jean en lecture.


Q-31 Afficher le contenu d'un répertoire

Écrire un script bash listedir.sh permettant d'afficher le contenu d'un répertoire en séparant les fichiers et les (sous)répertoires.

Exemple d'utilisation :

$ ./listdir.sh 

 

affichera :

--------------   Fichiers dans /etc/rc.d --------------------

rc

rc.local

rc.sysinit

--------------   Repertoires dans /etc/rc.d --------------------

init.d

rc0.d

rc1.d

rc2.d

rc3.d

rc4.d

rc5.d

rc6.d


Q-32 Lister les utilisateurs

Écrire un script bash affichant la liste des noms de login des utilisateurs définis dans /etc/passwd ayant un UID supérieur à 500.

Indication : for in $(cat /etc/passwd) permet de parcourir les lignes du dit fichier.


Q-33 lecture au clavier

La commande bash read permet de lire une chaîne au clavier et de l'affecter à une variable. exemple :

echo -n "Entrer votre nom: "

read nom

echo "Votre nom est $nom"

 

La commande file affiche des informations sur le contenu d'un fichier (elle applique des règles basées sur l'examen rapide du contenu du fichier).

Les fichier de texte peuvent être affiché page par page avec la commande more.


1-  Tester ces trois commandes;


2-  Écrire un script qui propose à l'utilisateur de visualiser page par page chaque fichier texte du répertoire spécifié en argument. Le script affichera pour chaque fichier texte (et seulement ceux là) la question "voulez vous visualiser le fichier machintruc ?". En cas de réponse positive, il lancera more, avant de passer à l'examen du fichier suivant.

 

 

B-   Plat principal

 

0- Un fichier contient des entiers au format binaire, un par ligne. Donner une commande sed qui permet d'afficher les entiers qui commencent et se terminent par 1 avec au milieu 2 à 4 zéro:

 

Solution :

$ sed -n '/10\{2,4\}1/p' demofile2

 

1- Ecrire un programme shell qui prend en paramètre un exécutable, qui va retrouver tous les numéros de processus et les détruire. Il s’agit de simuler la commande killall. Vous pouvez vous inspirer du code suivant :

 

#!/bin/bash

TITI="`echo $1`"

for i in `ps -hu | cut -c 8-14 `

do

  TOTO=`ps -h $i | cut -c 22- | grep -G $TITI | cut -f 1 -d " "`

  NUM=`echo $TOTO | wc -c `

  if test $NUM -ne 1; then

          ps -h $i

          echo "Detruction du PID $NUM"

          # kill –9 $NUM

  fi

done

 Dans cette question un script prend en paramètre le nom d'un

exécutable et détruit (commande kill) toutes les instances de cet

exécutable. On peut simplement utiliser 'killall

<nom_prog_a_supprimer>' mais c'est vraiment trop simple.


Un algorithme possible est le suivant :


pour toutes les lignes renvoyées par la commande 'ps aux' faire

repérer le nom de l'exécutable;

// ceci ce fait avec un 'cut' et des options appropriées

si ce nom = $1 alors

repérer le numéro de processus (PID) associe a la commande;

// ceci ce fait avec un 'cut' et des options appropriées

kill $PID

finsi

finpour


Une autre possibilité est d'utiliser des options appropriées pour la

commande ps. Le manuel nous dit :


Print only the process IDs of syslogd:

ps -C syslogd -o pid=


Print only the name of PID 42:

ps -p 42 -o comm=


Ainsi on a:

cerin@taipei:~/public_html/SE$ ps -C emacs -o pid=

8145

cerin@taipei:~/public_html/SE$ ps -p 8145 -o comm=

emacs

cerin@taipei:~/public_html/SE$ ps -p `ps -C emacs -o pid=` -o comm=

emacs



On peut alors écrire :

#!/bin/bash


if test `ps -C $1 -o pid=`

then

MyPid=`ps -C $1 -o pid=`

echo $MyPid

#kill -9 $MyPiD

fi


mais ceci ne fonctionne que pour une seule instance du programme:


cerin@taipei:~/public_html/SE$ ps aux | grep emacs

cerin 8145 0.2 1.3 19576 14372 pts/0 S 12:58 0:02 emacs Aide.txt

cerin 9942 16.1 1.4 19848 14588 pts/0 S 13:11 0:01 emacs

cerin 9960 0.0 0.0 4144 852 pts/0 S+ 13:12 0:00 grep emacs

cerin@taipei:~/public_html/SE$ /bin/sh test1.bash emacs

test1.bash: line 3: test: 8145: unary operator expected

cerin@taipei:~/public_html/SE$ ps -C emacs -o pid=

8145

9942

cerin@taipei:~/public_html/SE$


On voit que ps retourne des lignes ! On utilise alors l'une ou l'autre

des possibilités suivantes :


#!/bin/bash


MyPid=\"`ps -C $1 -o pid=`\"

#echo $MyPid

if test "$MyPid"!=""

then

for MyPid in `ps -C $1 -o pid=`

do

echo $MyPid

#kill -9 $MyPiD

done

fi


#

# Ou plus simplement

#

for MyPid in `ps -C $1 -o pid=`

do

echo $MyPid

#kill -9 $MyPiD

done


2- Le texte qui suit permet va générer un fichier au format HTML. Expliquer le fonctionnement général en isolant les différentes parties. Expliquer les parties les plus techniques. Exécuter le code à partir d’un fichier de données que vous avez à créer. Rajouter l’envoi d’un mail à vous même (voir commande mail) dont le corps sera le fichier produit. Rajouter également le contrôle du nombre de paramêtres dans le fichier d’entrée. Vérifiez que les objets qui doivent être de type entier dans le fichier d’entrée le sont bien.

 

#!/bin/sh

 

# pour digerer le formulaire de registration

 

echo Content-type: text/HTML

echo

cat > /tmp/BIDON

 

NUMERO=`expr 0 + 1`

for i in `echo 1 2 3 4 5 6 7 8 9 10 11 12 13 14`

do

#eval TI$NUMERO="`cut -f $i -d \= /tmp/BIDON | cut -f 2 -d \& `"

#    NUMERO=`expr $NUMERO + 1`

    j=`expr $i + 1`

    eval TI$i="\"`cut -f $j -d \= /tmp/BIDON | cut -f 1 -d \& | tr \+ \ | sed -e '1,$s/\%0D\%0A/ /g' | sed -e '1,$s/\%09/ /g' | sed -e '1,$s/\%E9/\&eacute;/g' | sed -e '1,$s/\%7E/\~/g' | sed -e '1,$s/\%23/\#/g'  | sed -e '1,$s/\%7B/\{/g' | sed -e '1,$s/\%7D/\}/g' | sed -e '1,$s/\%28/\(/g' | sed -e '1,$s/\%29/\)/g' | sed -e '1,$s/\%5B/\[/g' | sed -e '1,$s/\%5D/\]/g' | sed -e '1,$s/\%E8/\&egrave;/g' | sed -e '1,$s/\%E0/\&agrave;/g' | sed -e '1,$s/\%26/\&amp;/g' | sed -e '1,$s/\%22/\&quot;/g' | sed -e '1,$s/\%7C/\|/g' | sed -e '1,$s/\%3C/\&lt;/g' | sed -e '1,$s/\%3E/\&gt;/g' | sed -e '1,$s/\%E7/\&ccedil;/g' | sed -e '1,$s/\%5E/\^/g' | sed -e '1,$s/\%F9/\&ugrave;/g' | sed -e '1,$s/\%25/\%/g' | sed -e '1,$s/\%2B/\+/g' | sed -e '1,$s/\%24/\$/g' | sed -e '1,$s/\%21/\!/g' | sed -e '1,$s/\%2F/\//g' | sed -e '1,$s/\%3A/\:/g' | sed -e '1,$s/\%3B/\;/g' | sed -e '1,$s/\%2C/\,/g' | sed -e '1,$s/\%3F/\?/g' | sed -e '1,$s/\%5C/\&backslash;/g'`\""

#    TI=$TI:"`cut -f $j -d \= /tmp/BIDON | cut -f 1 -d \& #| tr \+ \ | sed -e '1,$s/\%0D\%0A/ /g' | sed -e #'1,$s/\%09/ /g' `"

#    NUMERO=`expr $NUMERO + 1`

done

 

case $TI13 in

        "80")

               NUM=80

               ;;

        "284")

               NUM=284

               ;;

        "334")

               NUM=334

               ;;

        "317")

               NUM=317

               ;;

        "384")

               NUM=384

               ;;

esac

DEST="/tmp/registration-iscee98.html"

#rm /tmp/BIDON

EXEL="./exel.txt"

echo "$TI1   $TI2   $TI3   $TI4   $TI5   $TI6   $TI7   $TI8   $TI9   $TI10  $TI11        $TI12  $TI13  $TI14" >> $EXEL

#-----------------------------------------------------

cat << FIN1 > $DEST

<HTML>

<HEAD>

<TITLE>

ISCEE'98 Registration Form

</TITLE>

</HEAD>

<BODY BGCOLOR="#FFFFFF">

<CENTER>

<H3>

ISCEE'98 Registration Form

</H3>

Oct 8-9, 1998, Universit&eacute; de Melbourne</CENTER>

<HR>

<UL><P>

 

 

<B>Last name:</B> $TI1 &nbsp;&nbsp;

<B>First name:</B> $TI2<br>

<b>Name on Badge:</b> $TI3<br>

<B>Affiliation: </B>$TI4<br>

<b>Address:</b> $TI5<br>

<B>City: </B>$TI6<br>

<B>Phone Number: </B>$TI7 &nbsp;&nbsp;

<B>Fax Number: </B>$TI8<br>

<b>E-Mail: </b>$TI9<br>

<B>IEEE Number:</B>$TI10<br>

<b>HTTP: </b>$TI11<br>

<b>Special Diary:</b>$TI12<br>

<b>Registration Fees: </b>$TI13 US$ or `expr 6 \* $NUM` FF<br>

<b>Comment: </b> $TI14<br>

<P>

<br>

<br>

<P>Signature ____________________________<P>

</UL><P>

</UL><HR>

<pre>

Way of Payment (**):

(**) Change fees will be paid by the participant.

 

1- By check payable to VERNE-ADER

 

2- By administration order form to VERNE-ADER:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UPJV-Chemin du Thil-80025 Amiens Cedex 1-France

 

3- By direct BankTransfer on the account:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Credit Lyonnais Melbourne 30002/05024/0000079046K20

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(Please, indicate your identity and the name ISCEE'98.)

</pre>

Registration form along with payment must be MAILED to:<P>

<B>ISCEE'98</B><BR>

Melbourne - Australia<br>

Email: iscee98@melbourne.au

<p>

Please, FAX to 33-322827502 this form AND a copie of your

bank transfert form which contains the symposium name and your name in order to identify the payment. Thanks.

</p>

</UL>

</BODY>

</HTML>

FIN1

cat /tmp/registration-iscee98.html

 

3) On veut un script permettant de formater un fichier qui contient des lignes organisées en colonnes mais le séparateur de colonne et un ou plusieurs blancs ou encore \t. Par exemple, vous pouvez utiliser la commande column comme suit :

 

Ordinateur-de-Christophe-Cerin:~ cerin$ column -t titi

abc

efg  asdf

ijk  ert   fgv

qqq

Ordinateur-de-Christophe-Cerin:~ cerin$ more titi

        abc

efg asdf

        ijk ert    fgv

qqq

 

 Il vous faut donc simuler la commande column. Utilisez sed par exemple.

 

4) Le script suivant prend en paramètre un fichier texte et génère un fichier HTML :

 

Ordinateur-de-Christophe-Cerin:~ cerin$ more script.sed

2i\

<html>\

<head><title>sed generated html</title></head>\

<body bgcolor="#ffffff">\

<pre>

$a\

</pre>\

</body>\

</html>

 

Ordinateur-de-Christophe-Cerin:~ cerin$ more titi

        abc

efg asdf

        ijk ert         fgv

qqq

 

 

 

Ordinateur-de-Christophe-Cerin:~ cerin$

 

Ordinateur-de-Christophe-Cerin:~ cerin$ sed -f script.sed titi

        abc

<html>

<head><title>sed generated html</title></head>

<body bgcolor="#ffffff">

<pre>

efg asdf

        ijk ert         fgv

qqq

 

 

 

</pre>

</body>

</html>Ordinateur-de-Christophe-Cerin:~ cerin$

 

Le script repose sur les commandes d'insertion et de concaténation de sed. Veuillez le modifier pour insérer dès la première ligne et ajouter un \n en fin de fichier.  On vous demande ensuite de modifier script.sed pour que l'on puisse procéder au traitement suivant sur le fichier inséré : suppression des <tab> et blancs en tête de chaque ligne et mettre un seul blanc entre les mots. Supprimer également les lignes blanches de fin.

 

Solution :

 

# on tout ce qui n'est pas une lettre en tete

s/[^[a-z]*//

# on enleve les \tab : attention il faut taper le

# caractere tab dans le motif

s/\(.\) \(.\)/\1\2/

 

1i\

<html>\

<head><title>sed generated html</title></head>\

<body bgcolor="#ffffff">\

<pre>

$a\

</pre>\

</body>\

</html>

# on enleve toutes les lignes blaches !!! bizarre

/^$/d

 

5- Utilisez sed pour réaliser les actions suivantes :

1. Print a list of files in your scripts directory, ending in ".sh". Mind that you might have to unalias ls. Put the result in a temporary file.

2. Fabriquer une liste des fichiers dans /usr/bin qui ont un a en deuxième position. Ranger le résultat dans un fichier temporaire.

3. Détruire les 3 premières lignes du fichier temporaire.

4. Afficher sur la sortie standard les fichier ayant comme motif "an".

5. Create a file holding sed commands to perform the previous two tasks. Add an extra command to this file that adds a string like "*** This might have something to do with man and man pages ***" in the line preceding every occurence of the string "man". Check the results.

6. A long listing of the root directory, /, is used for input. Create a file holding sed commands that check for symbolic links and plain files. If a file is a symbolic link, precede it with a line like "--This is a symlink--". If the file is a plain file, add a string on the same line, adding a comment like "<--- this is a plain file".

 

 

C-   Dessert

 

1- Etude d’un code

                                                                  i.      Après avoir mis des commentaires dans le code qui suit, dites en une phrase ce que fait le code.

                                                                    ii.      Ajouter les codes permettant de créer les répertoires s’ils ne sont pas présents et qui va créer quelques fichiers « bidons » en entrée si le repertoire d’entrée n’existait pas.

                                                                      iii.      Exécutez le code et lister le résultat.

 

#!/bin/bash

#

 

#

# File    : addlog.sh

# Date    : avril 2nd, 2002

#

# Purpose:

# Args   : -h for help

#          $1, dir1

#

 

 

# ------------------- Local Function

 

Help()

{

        echo

        echo `basename $0` [-h] dir1

        echo " -h : get this help msg";

        echo

 }

 

# ------------------- Main Function

 

# -------------------

 

if [ $# -lt 1 ]; then

        echo

        echo `basename $0` : too few args

        Help

        exit 1

fi

 

if [ $1 = "-h" ]; then

        Help

        exit 0

fi

 

inDir=$1

shift

 

if [ -d $inDir ]; then

    dirExist=1

else

    dirExist=0

fi

 

if [ $dirExist -ne 1 ]; then

    echo "$dirIn is not a valid directory"

    exit 2

fi

 

 

# ------------------- Main loop

 

scriptLogFile="ADDLOG.txt"

if [ -f $scriptLogFile ]; then

    echo $inDir >> $scriptLogFile

else

    echo $inDir > $scriptLogFile

fi

 

 

localDir=`pwd`

outDir=$localDir/total

inDir=$localDir/$inDir

 

 

 

cd $outDir

 

for fileIn in `ls $inDir/*.log`; do

 

  fileOut=`basename $fileIn`

 

  if [ -f $fileOut ]; then

 

    tempFile=`date | sed 's/ /_/g' | sed 's/:/_/g'`

    cp $fileIn $tempFile

    $localDir/rmline1.sh $tempFile

 

    cat $tempFile >> $fileOut

    rm -f $tempFile

 

  else

 

    cp $fileIn $fileOut

 

  fi

 

done

 

 

cd $localDir