# q1.sh #!/bin/bash #Ecrire un script qui affiche la somme arithmétique des arguments #passés en paramètre, quelque soit leur nombre while [ $# -ge 1 ]; do ((somme+=$1)) shift done echo La somme des arguments est $somme # q2.sh #!/bin/bash #Ecrire un script qui affiche "hello world" autant de fois que passé #en paramètre du script times=$1 while [ $times -gt 0 ] ; do ((times--)) echo hello world done # q3.sh #!/bin/bash #Ecrire un script qui s'affiche lui-même à partir de la variable $0 cat $0 # q4.sh #!/bin/bash # Ecrire un script qui calcule votre age en prenant votre date # de naissance en paramètre. Indication : utiliser la commande date # le calcul de l'age est fait en jours # Usage ex : ./q4.sh "14 June 1978" date_today_in_sec=$(date --date=now +%s) #calcul de la date de naissance en seconde if [ $# -lt 1 ]; then echo "Entrez votre date de naissance (Ex : 14 June 1992)" read date_of_birth date_of_birth_in_sec=$(date --date="$date_of_birth" +%s) else date_of_birth_in_sec=$(date --date="$1" +%s) fi #echo $date_today_in_sec #echo $date_of_birth_in_sec age_in_sec=$((date_today_in_sec - date_of_birth_in_sec)) #echo $age_in_sec echo vous avez $(($age_in_sec/(60*60*24))) jours # q5.sh #!/bin/bash #Ecrire un script qui prends deux entiers a et b en paramètre et #qui affiche, selon les valeurs de a et b : #- $a est plus petit que $b #- $a est égal à $b #- $a est plus grand que $b if [ $1 -lt $2 ]; then echo $1 est plus petit que $2 fi if [ $1 -eq $2 ]; then echo $1 est égal à $2 fi if [ $1 -gt $2 ]; then echo $1 est plus grand que $2 fi # q6.sh #!/bin/bash #Ecrire un script qui, dans son répertoire de travail courant, #renomme tous les fichiers d'une extension donnée dans une autre #extension donnée en paramètre. On veillera à ce que n'importe #quel nom de fichier puisse être utilisée. On suppose que l'extension #commence à partir du caractère "." du fichier et qu'il n'y a qu'un #seul point dans le fichier. if [ $# -lt 2 ]; then echo "$0 renomme tous les fichiers du répertoire courant" echo "d'une extension1 donnée vers extension2 donnée." echo "Usage : $0 " exit fi for i in *.$1; do if [ -f $i ]; then mv "$i" "${i%.*}.$2"; fi done # q7.sh #!/bin/bash #Ecrire un script qui : #a) stocke la liste des arguments passés en paramètre dans un tableau, #dans l'ordre où ils apparaissent dans la ligne de commande. #b) Affiche ces arguments à partir du tableau précédemment construit #c) On suppose que ces arguments sont des entiers, modifier le script #pour qu'il trie puis affiche le contenu du tableau d'entier. #en paramètre # Question 7 : Joachim Schmidt # ITI2 soir # Programmation système if [[ $# -ne 0 ]] ; then i=0 #shopt -s extglob for argu in $* ; do if [[ $argu = ?([-])+([0-9]) ]] ; then tab[$i]=$argu ((i=i+1)) else echo "L'argument '$i' n'est pas un nombre entier." echo "Dès lors, il n''est pas inclu dans le tableau." fi done tabTri=$( echo ${tab[*]} | sed -e 's/ /\n/g' | sort -n ) echo ${tabTri} else echo "Le programme prend en argument une liste de nombres entiers!" fi # q8.sh #!/bin/bash # #Ecrire un shell script qui initialise une variable au nombre #de seconde de l'heure courante (par exemple si la commande date #renvoir 12:42:14, le nombre est 14). Cette variable sera à #deviner par l'utilisateur du script. # #A chaque essai faux, le script indique à l'utilisateur si #le nombre entré est plus grand ou plus petit que le nombre #à deviner. # #Le script donne 5 essais à l'utilisateur pour deviner le nombre, #après cela, le jeu se termine et affiche quel était le nombre #à deviner. devine=$(date +%S) found=false echo -n Devine un nombre entre 0 et 59: read number for i in {1..4}; do if [ $devine -gt $number ]; then echo -n Entre un nombre plus grand: read number elif [ $devine -lt $number ]; then echo -n Entre un nombre plus petit: read number elif [ $devine -eq $number ]; then found=true fi done if $found; then echo Tu as trouvé le nombre! else echo Tous les essais sont utilisés! Le nombre était $devine fi # q9.sh #!/bin/bash # # Ecrire un script qui liste tous les fichiers du répertoire de # travail courant contenant un certain motif, renseigné en paramètre # du script. Le format de sortie du script devra respecter exactement # le format suivant de l'exemple : # # mickael@computer:~$ source list_file.sh toto # mickael@computer:~$ source list_file.sh titi # Le fichier essai.txt contient 1 instance du motif titi # Le fichier data.txt contient 8 instances du motif titi # Le fichier lines.txt contient 11 instances du motif tt # # Le script ne lit que les fichiers qui ont au moins une instance # du motif, les fichiers n'ayant aucune instances ne sont pas listés. # Si il n'y a qu'une seule instance, instance est au singulier. pattern=$1 for i in *; do if [ -f $i ]; then nb_inst=$(grep $pattern $i | wc -l ); if [ $nb_inst -eq 1 ]; then echo le fichier $i contient $nb_inst instance du motif $pattern; fi if [ $nb_inst -gt 1 ]; then echo le fichier $i contient $nb_inst instances du motif $pattern; fi fi done # q10.sh #!/bin/bash # Ecrire un script qui affiche tous les ancètres du processus courant. # Le script devra utiliser une fonction récursive qui affiche à chaque fois # le processus parent d'un processus donné en paramètre, à moins que le numéro # de processus soit le processus init, qui n'a pas de processus parent. # Indication : utiliser la commande ps avec les bonnes options avec un utilitaire d'extraction de texte comme awk ou sed. print_proc_ancestor() { ppid=$(ps -o pid= -o ppid= -o fname= $1 | awk '{print $2}') pname=$(ps -o pid= -o ppid= -o fname= $1 | awk '{print $3}') echo $ppid:$pname if [ $ppid -eq 0 ] then echo "Fini" else print_proc_ancestor $ppid fi } echo printing ancestor of process $$ print_proc_ancestor $$ # q11.sh # Ecrire un shell script qui permet d'effacer un fichier (ou plusieurs fichiers) de manière # non définitive. Plus particulièrement, l'idée sera de déplacer les fichiers dans une # poubelle. Définir une option pour détruire la poubelle ou pour détruire un fichier de # manière définitive (dans les deux cas demander à l'utilisateur s'il/elle est sûr(e)). # Indications : utiliser les tests pour vérifier qu'un fichier ou que la poubelle existent; si la # poubelle n'existe pas il faudra la créer. Utiliser la commande mv pour le déplacement des # fichiers et rm pour la destruction. #!/bin/sh # # Script qui met au moins un fichier dans une poubelle # poubelle() { if [ $1 = -P ] then echo -n "La poubelle va etre effacee ! Etes-vous sur ? (o/n) " read reponse if [ $reponse = o ] then if test -d maPoubelle then rm -r maPoubelle else echo "La poubelle n'existe pas !" fi fi return fi # if [ $1 = -f ] then echo -n "Effacement definitif ! Etes-vous sur ? (o/n) " read reponse if [ $reponse = o ] then for fich in $@ do if [ $fich = -f ] then xx=1 elif [ -d $fich ] then echo "Je ne peux pas effacer le repertoire $fich" elif [ -e $fich ] then rm $fich fi done fi return fi # if test -d maPoubelle then echo "Migration du/des fichier(s) vers la poubelle ..." else echo "La poubelle n'existe pas; je vais la creer !" mkdir maPoubelle fi # for fich in $@ do if [ -d $fich ] then echo "Cannot remove directory $fich" elif [ -e $fich ] then mv $fich maPoubelle/. fi done } if [ $# -eq 0 ] then echo "monRm ... " echo "monRm -P (pour effacer la poubelle)" echo "monRm -f ... (pour effacer definitivement)" else poubelle $@ fi # q12.sh #!/bin/bash #la commande bc (bash calculator) permet d'afficher un nombre en base 2 en précisant la variable obase=2 avant d'afficher le nombre. #Par exemple la commande echo "obase=2;3 | bc" affichera 3 en binaire, c'est à dire 11. #A l'aide des commandes hexdump, bc et echo, ecrire un script qui affiche le contenu d'un fichier en binaire octet par octet. if [ $# -lt 1 ] then echo -e "Vous devez passer en paramètre le nom d'un fichier" exit 0 elif [ ! -f $1 ] then echo -e "Ce n'est pas un fichier" exit 0 fi chaine=$(hexdump -v -e '' -e '/1 "%d" " "' "$1") for i in $chaine do echo "obase=2;$i" | bc done # q13.sh #!/bin/bash #Ecrire un script qui vérifie si chaque mot d'un fichier est bien dans un dictionnaire orthographique. Le dictionnaire orthographique #est implémenté par un fichier régulier contenant un mot correctment orthographié par ligne. Le script doit afficher les mots #qu'il n'a pas trouvé dans dictionnaire. Pour les mots du texte présent dans le dictionnaire, le script n'affiche rien. # #- Avant de vérifier l'orthographe, Les mots du texte devront être mis en minuscule # pour éviter une détection de fautes qui n'en est pas une : dans le dictionnaire tous les mots sont en minuscule. # #- La vérification des mots du texte devra se faire après classement alphabétique des mots du texte dans une liste séparée par # des espace ou des retour à la ligne. L'orthographe de chaque mot sera ensuite vérifiée, en commançant par les premiers mots # du classement. # #- Si un même mot apparaît plusieurs fois dans le texte, on ne vérifiera son orthographe qu'une seule fois : Chaque mot de la liste # classée doit donc être unique dans la liste. # create dictionnary file DICTIONNARY=./dictionnary.txt cat << EOF > $DICTIONNARY this is a word from the dictionnary EOF makeword () { while read line do for word in $line; do echo $word; done done } lowercase() { tr '[:upper:]' '[:lower:]' } mismatch() { while read word; do if ! grep -w $word $DICTIONNARY > /dev/null then echo $word fi done } makeword | lowercase | sort | uniq | mismatch # q14.sh #!/bin/bash #Ecrire un script qui affiche les 100 mots les plus utilisés d'un texte et combien de fois ils ont été utilisés dans un fichier #texte passé en paramètre. Si y a moins de 100 mots, le script affiche les statistiques de tous les mots. #Indication : utiliser les tableaux associatifs de bash. # #exemple d'utilisation : # #mickael@computer:~$ source 100mots.sh toto #Le mot "et" apparaît 114 fois #Le mot "est" apparaît" 54 fois #Le mot "texte" apparaît" 11 fois makeword () { while read line do for word in $line; do echo $word; done done } lowercase() { tr '[:upper:]' '[:lower:]' } store_stats() { while read word; do if [ -z words_stats[\"$words\"] ]; then words_stats[\"$word\"]=1 else ((words_stats[\"$word\"]+=1)) fi done for key in ${!words_stats[*]}; do echo $key:${words_stats[$key]} done } declare -g -A words_stats; makeword | lowercase | sort | store_stats | sort -n -k 2 -r -t : | head -n 100 # q15.sh #!/bin/bash #Ecrire un script qui permet de lancer une compilation parallèle d'un projet. Ce script exécutera plusieurs processus gcc, #chacun ayant à compiler un ou plusieurs fichiers à compiler distincts de tous les autres. Le script prendra une option qui #indiquera le nombre de processus de compilation à exécuter en même temps. Le script devra attendre #que l'ensemble des processus de compilation soient terminés (voir la commande interne wait) avant de faire l'édition #des liens. Par défaut et pour simplifier, on considère que tous les fichiers .c du répertoire courant seront à compiler #dans un seul exécutable. # Note : solution partielle. nb_running_process=0 max_running_process=4 compilation_options="-g -O2" binary_name="test" function comp_parallele() { encore_des_fichiers="true" while [ $encore_des_fichiers == "true" ]; do until [ $(jobs -r | grep gcc | wc -l) -ge $max_running_process ]; do if [ $# -ge 1 ] then echo "compiling $1 ( $# more files to compile )" gcc $compilation_options -c $1 & fi if ! shift then encore_des_fichiers="false" break fi done done } comp_parallele *.c wait gcc -o $binary_name *.o # q16.sh #!/bin/bash #Ecrire un script qui utilise la commande wget, diff et date pour vérifier régulièrement les changements effectués sur une #adresse web. Ce script, récupèrera un contenu http à une adresse donnée en paramètre, et stockera ce contenu dans un fichier #pour comparaison avec la prochaine récupération de contenu à la même adresse. Si le contenu à changé, le script créé un nouveau #fichier avec une date dans son nom indiquant la date de détection du dernier changement, ainsi que le résultat de la commande #diff dans son contenu. URL="http://infolibre.ch/hepia/progsysteme-2014-2015/" current_content_path=/tmp/current_content.html current_saved_content_path=last_saved_content.html #how often do we check the differences, in seconds check_every=60 if [ $# -lt 1 ] then echo "Using default URL $URL" else URL=$1 echo "Using URL $1" fi while true; do #get current content rm -f $current_content_path wget $URL -nc -O $current_content_path #check if the current content is different from the last one saved. #if there is no last one content, i.e file does not exist, simply copy current content. #if yes : update last content only if they are differences between last content saved and current content #if no : do nothing if [ -f $current_saved_content_path ] then #exit code of diff is 0 if there are no difference between two files if diff -C $current_content_path $current_saved_content_path > /tmp/diff then echo "They are no differences between last saved content and current content" else echo "They are differences between last saved content and current content" current_date=$(date +%d%m%y-%H%M) cp $current_saved_content_path $current_saved_content_path.$current_date echo "<-- Differences $current_date" >> $current_saved_content_path.$current_date cat /tmp/diff >> $current_saved_content_path.$current_date echo "-->" >> $current_saved_content_path.$current_date cp $current_content_path $current_saved_content_path fi else cp $current_content_path $current_saved_content_path fi sleep $check_every done