TD/TP1 Scripts Shell 1 Exercices de TD 1. Écrire un script lscatx qui prend en entrée un nom de chier et qui traite ce nom de la façon suivante : si c est un répertoire, on afche son contenu au format long; si c est un chier non exécutable, on afche son contenu; si c est un chier exécutable, on lance son exécution. Le script afche une erreur si le nombre d arguments est incorrect ou si le nom fourni est celui d un chier qui n existe pas. # test du nombre d arguments if [ $# -ne 1 ] ; then echo "Usage : $0 chier" # Est-ce que le chier existe? if [! -e $1 ] ; then echo "$1 n est pas un chier existant" # Si c est un dossier if [ -d $1 ] ; then ls -l $1 elif [ -x $1 ] ; then # Si c est un exécutable./$1 # sinon, on afche le contenu cat $1 2. Écrire un script fusion qui prend en arguments les noms de 3 chiers f1, f2 et f3 et qui copie f1 puis f2 dans f3. Le script afche une erreur si le nombre d arguments est incorrect, si f1 ou f2 ne sont pas des chiers ordinaires, ou si l opération est impossible. if [ $# -ne 3 ] ; then echo "Usage : $0 f1 f2 f3" if [! -f $1 ] [! -f $2] ; then echo "Fichiers d entrée incorrects" cat $1 $2 > $3 2>/dev/null echo "Erreur lors de l opération de fusion" 1
3. Écrire un script compile qui prend en arguments deux chiers exec et c.c et qui permet de compiler c.c avec gcc en un exécutable exec. Rappel : la compilation par gcc s obtient en faisant gcc -o exec c.c Une copie de exec sera ensuite placée dans le répertoire bin de l utilisateur. Le script afche une erreur si le nombre d arguments est incorrect ou si la compilation ne s est pas déroulée correctement. if [ $# -ne 2 ] ; then echo "Usage : $0 chier[.c.c.cpp] exec" gcc $1 -o $2 echo "Erreur de compilation" cp $2 ${HOME}/bin/ 4. Écrire un script scpip qui prend en arguments une adresse IP adr, un nom de chier c et éventuellement un nom d utilisateur, et qui tente de copier le chier vers cette adresse en utilisant scp. Rappel : pour copier un chier c depuis sa propre machine vers une machine adr en tant qu utilisateur user, faire scp c user@adr :c Si le nom d utilisateur n est pas fourni, on utilise le nom de l utilisateur qui exécute le script. Le script afche une erreur si le nombre d arguments est incorrect ou si l opération de copie a échoué. if [ $# -eq 2 ] ; then scp $2 ${USER}@$1:$2 elif [ $# -eq 3 ]; then scp $2 $3@$1:$2 echo "Usage : $0 adresseip chier [utilisateur]" echo "Erreur lors de la copie" 2
5. Le répertoire /proc contient un pseudo-système de chiers dans lequel, dès qu un processus est lancé, le système crée un répertoire XXX/ (où XXX est le PID du processus). On trouve dans ce répertoire un chier status dont la première ligne contient le nom de l exécutable associé à XXX. Exemple : crespin@msi : $ head -n 1 /proc/24204/status Name : bash Écrire un script getexe qui afche pour un PID donné le nom de l exécutable associé. Le script afche une erreur si le nombre d arguments est incorrect ou si le PID est invalide. if [ $# -ne 1 ]; then echo "Usage $0 pid" if [! -d "/proc/$1" ]; then echo "$1 n est pas un PID valide" head -n 1 /prov/$1/status cut -f2 6. Ecrire un script mvext qui prend en arguments un nom de chier et une extension et qui renomme le chier en utilisant cette extension. Si le chier n a aucune extension, l extension fournie lui est simplement ajoutée. Exemple :./mvext toto.jpg DAT renomme le chier toto.jpg en toto.dat et./mvext toto DAT renomme le chier toto en toto.dat Le script afche une erreur si le nombre d arguments est incorrect ou si le renommage est impossible. if [ $# -ne 2 ]; then echo "Usage $0 chier extension" nouv=$(echo $1 cut -d. -f1).$2 if mv $1 $nouv 2>/dev/null ; then echo "$1 a été renommé en $nouv" echo "Impossible de renommé $1 en $nouv" 3
7. Écrire un script calc qui prend en arguments un entier, un opérateur (+ ou -) puis un entier, puis qui afche le résultat de l opération. Exemple :./calc 1 + 2 doit afcher la valeur 3 Le script afche une erreur si le nombre d arguments est incorrect, ou si un des arguments est incorrect (par exemple si on fait./calc toto * 3) #/bin/bash if [ $# -ne 3 ]; then echo "Usage : $0 nb1 [+ -] nb2" # (grep -v renvoi le résultat inverse de la recherche (-q = quiet)) # en mode "quiet" grep n afche rien mais renvoi 1 si le pattern a été trouvé, 0 sinon if echo $1 grep -qv "ˆ[0-9]\+$" ; then echo "$1 n est pas un nombre entier" if echo $3 grep -qv "ˆ[0-9]\+$" ; then echo "$3 n est pas un nombre entier" case "$2" in \+) let res=$1+$3 ;; \-) let res=$1-$3 ;; *) echo "$2 n est pas pris en charge" exit 4 esac echo "Result = $res" 4
2 Exercices de TP 1. Améliorer le précédent script lscatx en vériant, avant de traiter le chier, que l utilisateur a les droits de lecture et que la taille est supérieure à 0. if [ $# -ne 1 ] ; then echo "Usage : $0 chier" if [! -e $1 ] ; then echo "$1 n est pas un chier existant" if [! -r $1 ] [! -s $1 ] ;then echo "$1 n est pas un chier exploitable" if [ -d $1 ] ; then ls -l $1 elif [ -x $1 ] ; then./$1 cat $1 2. Améliorer le précédent script fusion en vériant que les chiers f1 et f2 sont accessibles en lecture et ont une taille supérieure à 0. Vérier également que l utilisateur a le droit d écriture dans le répertoire courant. if [ $# -ne 3 ] ; then echo "Usage : $0 f1 f2 f3" if [! -f $1 ] [! -f $2 ] ; then echo "Fichiers d entrée incorrects" if [! -r $1 ] [! -s $1 ] [! -r $2 ] [! -s $2 ] ; then echo "Fichiers d entrée non lisibles" if [! -w "./" ] ; then echo "Impossible d écrire dans le répertoire courant" exit 4 cat $1 $2 > $3 2>/dev/null echo "Erreur lors de l opération de fusion" exit 5 5
3. Améliorer le précédent script compile en ajoutant la possibilité de spécier plusieurs chiers sources à compiler, en faisant par exemple./compile exec c1.c c2.c... (utiliser shift). if [[ $# -lt 2 ]] ; then echo "Usage : $0 exec chier[.c.c.cpp] [chier2.c...]" while [[ $# -gt 1 ]] && [[ $? -eq 0 ]]; do gcc -c $2 shift done if [[ $? -ne 0 ]]; then echo "Il y a eu des erreurs lors de la compilation" gcc *.o -o $1 if [[ $? -ne 0 ]] ; then echo "Erreur lors de l édition de lien" cp $1 $HOME/bin/ 4. Améliorer le précédent script scpip en testant si l adresse fournie est bien une adresse ip au format numérique (par exemple 164.81.60.3) ou texte (par exemple info.msi.unilim.fr) en utilisant sed ou grep. if [[ $# -eq 2 ]] [[ $# -eq 3 ]] ; then if echo $1 grep -q "ˆ[[:digit:]]\+\(\.[[:digit:]]\+\)\{3\}$" ; then echo "Adresse IP au format numérique trouvé" elif echo $1 grep -q "ˆ[[:alpha:]]\+\(\.[[:alpha:]]\+\)*$"; then echo "Nom d hote trouvé" echo "Type d adresse non conforme" if [[ $# -eq 2 ]]; then scp $2 ${USER}@$1:$2 scp $2 $3@$1:$2 echo "Usage : $0 adresseip chier [utilisateur]" if [[ $? -ne 0 ]] ; then echo "Erreur lors de la copie" 6
5. En vous inspirant du précédent script getexe, écrire un nouveau script prenant en argument un nom de commande cmdname, et qui afche le numéro des processus correspondant à cette commande (utiliser le contenu des chiers status des processus stockés dans le répertoire /proc), ou un message d erreur si aucune commande correspondant à ce nom n a été lancée. if [[ $# -ne 1 ]]; then echo "Usage $0 cmdname" let found=0 # rappel : $( ) exécute ce qu il y a entre paranthèse comme une commande # et renvoi le résultat for i in $(ls /proc/); do if [[ -d "/proc/$i" ]] && [[ "$1" = $(head -n 1 /proc/$i/status cut -d \t -f2) ]]; then echo "Commande $1 trouvée pour le PID $i" let found=$found+1 # ou alors found = $(($found+1)) # le contenu de $(( )) est interprété de façon arithmétique # par exemple si a=2, $(($a+1)) renvoie 3 done if [[ $found -eq 0 ]]; then echo "Commande non trouvée" 6. Améliorer le précédent script calc en ajoutant les opérations * et / #/bin/bash if [ $# -ne 3 ]; then echo "Usage : $0 nb1 [+ - * /] nb2" if echo $1 grep -qv "ˆ[0-9]\+$" ; then echo "$1 n est pas un nombre entier" if echo $3 grep -qv "ˆ[0-9]\+$" ; then echo "$3 n est pas un nombre entier" case "$2" in "+") let res=$1+$3 ;; "-") let res=$1-$3 ;; "*") let res=$1*$3 ;; "/") let res=$1/$3 ;; *) echo "$2 n est pas pris en charge" exit 4 esac echo "Result = $res" 7