Scripts Shell

Les sections qui suivent ce chapitre s'inspirent notamment du livre Scripts shell Linux et Unix de Christophe Blaess qu'il est conseillé d'acquérir. L'ouvrage est orienté embarqué mais convient parfaitement pour un apprentissage précis, rapide, intéressant et dynamique.

Objectifs des certification

Linux Essentials

RHCE EX300

  1. System configuration and management
    • 1.9. Use shell scripting to automate system maintenance tasks.

LPIC 1

1. Scripts Bash : notions

  • Rudiments pour commencer à automatiser ses tâches d’administration en Bash

1.1. Scripts Bash

  • shebang
  • variables positionnelles
  • variables internes
  • fonctions et programme principal
  • fin de script
  • test
  • conditions
  • boucles
  • déboggage
  • ~/.bashrc
  • Références et exemples

1.2. Shebang

Le shebang, représenté par #!, est un en-tête d'un fichier texte qui indique au système d'exploitation que ce fichier n'est pas un fichier binaire mais un script (ensemble de commandes) ; sur la même ligne est précisé l'interpréteur permettant d'exécuter ce script. Pour indiquer au système qu’il s’agit d’un script qui sera interprété par bash on placera le shebang sur la première ligne :

#!/bin/bash

1.3. Hello World

#!/bin/bash
# script0.sh
echo "Hello World"
exit

Donner les droits d’exécution au script.

chmod +x script0.sh

1.4 Variables prépositionnées

Certaines variables ont une signification spéciale réservée. Ces variables sont très utilisées lors la création de scripts :

  • pour récupérer les paramètres transmis sur la ligne de commande,
  • pour savoir si une commande a échoué ou réussi,
  • pour automatiser le traitement de tous paramètres.

Liste de variables prépositionnées

  • $0 : nom du script. Plus précisément, il s'agit du paramètre 0 de la ligne de commande, équivalent de argv[0]
  • $1, $2, ..., $9 : respectivement premier, deuxième, ..., neuvième paramètre de la ligne de commande
  • $* : tous les paramètres vus comme un seul mot
  • $@ : tous les paramètres vus comme des mots séparés : "$@" équivaut à "$1" "$2" ...
  • $# : nombre de paramètres sur la ligne de commande
  • $- : options du shell
  • $? : code de retour de la dernière commande
  • \$\$ : PID du shell
  • $! : PID du dernier processus lancé en arrière-plan
  • $_ : dernier argument de la commande précédente

Par exemple :

#!/bin/bash
# script1.sh
echo "Nom du script $0"
echo "premier paramètre $1"
echo "second paramètre $2"
echo "PID du shell " \$\$
echo "code de retour $?"
exit

Donner les droits d’exécution au script :

chmod +ux script1.sh

Exécuter le script avec deux paramètres :

./script1.sh 10 zozo

1.5. Variables internes

En début de script, on peut définir la valeur de départ des variables utilisées dans le script.

VARIABLE="valeur"

Elles s'appellent comme ceci dans le script :

echo $VARIABLE

Il peut être utile de marquer les limites d'une variable avec les accolades.

echo ${VARIABLE}

Par exemple :

#!/bin/bash
# script2.sh
PRENOM="francois"
echo "dossier personnel /home/$PRENOM"
exit

1.6. Interaction utilisateur

La commande echo pose une question à l’utilisateur

La commande read lit les valeurs entrées au clavier et les stocke dans une variable à réutiliser.

echo "question"
read reponse
echo $response

On peut aller plus vite avec read -p :

read -p "question" reponse
echo $reponse

1.7. Fonctions

Pour déclarer une fonction, on utilise la syntaxe suivante :

maFonction()
{
  instructions
}

Ou de manière plus ancienne :

function ma_fonction {
   instructions
}

La déclaration d'une fonction doit toujours se situer avant son appel. On les mettra donc également en début de script.

Par exemple :

#!/bin/bash
# script3.sh
read -p "quel votre prénom ?" prenom
reponse() {
    echo $0
    echo "merci $prenom"
    exit 1
}
reponse
exit

2. Structures conditionnelles

2.1. Structure conditionnelle if/then

if condition; then
    commande1
else
    commande2
fi

2.2. Tests

La condition pourra contenir un test. Deux manières de réaliser un test (avec une préférence pour la première) :

[ expression ]

ou

test expression

Il y a beaucoup d’opérateurs disponibles pour réaliser des tests sur les fichiers, sur du texte ou sur des valeurs (arithmétique).

Par exemple :

#!/bin/bash
# script4.sh test si $passwdir existe
passwdir=/etc/passwdd
checkdir() {
    if [ -e $passwdir ]; then
        echo "le fichier $passwdir existe"
    else
        echo "le fichier $passwdir n'existe pas"
    fi
}
checkdir
exit

Variante : script4a.sh

On reprend la fonction checkdir qui lit la valeur variable donnée par l’utilisateur :

#!/bin/bash
# script4a.sh test si $passwdir existe
read -p "quel est le dossier à vérifier ?" passwdir
checkdir() {
    if [ -e $passwdir ]; then
        echo "le fichier $passwdir existe"
    else
        echo "le fichier $passwdir n'existe pas"
    fi
}
checkdir
exit

2.3. Structure de base d'un script

  1. Shebang
  2. Commentaire
  3. Fonction gestion de la syntaxe
  4. Fonction utile
  5. Fonction principale
  6. Fin
#!/bin/bash
# script5.sh structure de base d’un script
target=$1
usage() {
    echo "Usage: $0 <fichier/dossier>"
    exit
}
main() {
    ls -l $target
    echo "nombre de lignes : $(wc -l $target)"
    stat $target
}
if [ $# -lt 1 ]; then
    usage
elif [ $# -eq 1 ]; then
    main
else
    usage
fi
exit

2.4. Autres exemples de test

La page man de test pourrait nous inspirer.

execverif() {
    if [ -x $target ] ; then
        #('x' comme "e_x_ecutable")
        echo $target " est exécutable."
    else    
        echo $target " n'est pas exécutable."
    fi
}
#! /bin/sh
# 01_tmp.sh
dir="${HOME}/tmp/"
if [ -d ${dir} ] ; then
    rm -rf ${dir}
    echo "Le dossier de travail ${dir} existe et il est effacé"
fi    
mkdir ${dir}
echo "Le dossier de travail ${dir} est créé"

3. Boucles

3.1. Boucle for-do

Faire la même chose pour tous les éléments d'une liste. En programmation, on est souvent amené à faire la même chose pour tous les élément d'une liste. Dans un shell script, il est bien évidemment possible de ne pas réécrire dix fois la même chose. On dira que l'on fait une boucle. Dans la boucle for-do, la variable prendra successivement les valeurs dans la liste et les commandes seront répétées pour chacune de ces valeurs.

for variable in liste_de_valeur; do
    commande
    commande
done
for variable in liste do
    commandes
done
  • Par défaut, for utilise la liste in "$@" si on omet ce mot-clé.

Supposons que nous souhaitions créer 10 fichiers .tar.gz factices, en une seule ligne :

for num in 0 1 2 3 4 5 6 7 8 9; do touch fichier$num.tar.gz; done

Supposons que nous souhaitions renommer tous nos fichiers .tar.gz en .tar.gz.old :

#!/bin/bash
# script6.sh boucle
#x prend chacune des valeurs possibles correspondant au motif : *.tar.gz
for x in ./*.tar.gz ; do
    # tous les fichiers $x sont renommés $x.old
    echo "$x -> $x.old"
    mv "$x" "$x.old"
# on finit notre boucle
done
exit

Script inverse

Voici le script inverse, c’est sans compter sur d’autres outils pour d’autres situations :

#!/bin/sh
# script6r.sh inverse
#x prend chacune des valeurs possibles correspondant au motif : *.tar.gz.old
for x in ./*.tar.gz.old ; do
    # tous les fichiers $x sont renommés $x sans le .old
    echo "$x -> ${x%.old}"
    mv $x ${x%.old}
# on finit notre boucle
done
exit

3.2. Boucle while

Faire une même chose tant qu'un certaine condition est remplie. Pour faire une certaine chose tant qu'une condition est remplie, on utilise un boucle de type while-do et until-do.

while condition do
    commandes
done

Répète les commandes tant que la condition est vérifiée.

until condition do
    commandes
done

Répète les commandes jusqu'à ce que la condition soit vraie soit tant qu'elle est fausse.

  • Rupture avec break,
  • Reprise avec continue.

    while true; do commandes; done

Supposons, par exemple que vous souhaitiez afficher les 100 premiers nombres (pour une obscure raison) ou que vous vouliez créer 100 machines virtuelles.

#!/bin/bash
# script7.sh boucle while
i=0
while [ $i -lt 100 ] ; do
    echo $i
    i=$[$i+1]
done
exit

De manière plus élégante avec l’instruction for :

#!/bin/bash
# for ((initial;condition;action))
for ((i=0;i<100;i=i+1)); do
    echo $i
done
exit

3.3. Boucle case-esac (script8.sh)

L'instruction case ... esac permet de modifier le déroulement du script selon la valeur d'un paramètre ou d'une variable. On l'utilise le plus souvent quand les valeurs possibles sont en nombre restreint et peuvent être prévues. Les imprévus peuvent alors être représentés par le signe *.

Demandons par exemple à l'utilisateur s'il souhaite afficher ou non les fichiers cachés du répertoire en cours.

#!/bin/sh
# script8.sh case-esac
#pose la question et récupère la réponse
echo "Le contenu du répertoire courant va être affiché."
read -p "Souhaitez-vous afficher aussi les fichiers cachés (oui/non) : " reponse
#agit selon la réponse
case $reponse in
    oui)
        clear
        ls -a;;
    non)
        ls;;
    *) echo "Veuillez répondre par oui ou par non.";;
esac
exit

3.4. Divers

Boîtes de dialogue

On pourrait aussi s'intéresser à Whiptail : https://en.wikibooks.org/wiki/Bash_Shell_Scripting/Whiptail qui permet de créer des boîtes de dialogue.

Déboggage de script

On peut débogguer l’exécution du script en le lançant avec bash -x. Par exemple :

$ bash -x script7.sh

Etude de ~/.bashrc

$ head ~/.bashrc
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
    . /etc/bashrc
fi
# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=

4. Variables : concepts avancés

4.1. Affection des variables

  • On affecte une valeur à une variable en la déclarant variable=valeur
  • La valeur d'une variable est traitée par défaut comme une chaîne de caractère.
  • Le nom d'une variable ne peut pas commencer par un chiffre.

3.2. Protection des variables

On peut annuler la signification des caractères spéciaux comme *, ?, #, |, [], {} en utilisant des caractères d'échappement, qui sont également des caractères génériques.

\ Antislash

L'antislash \, qu'on appelle le caractère d'échappement, annule le sens de tous les caractères génériques, en forçant le shell à les interpréter littéralement.

$ echo \$var
$var
$ echo "\$var"
$var

" " Guillemets

Les guillemets (doubles) " " sont les guillemets faibles mais annulent la plupart des méta-caractères entourés à l'exception du tube (|), de l'antislash (\) et des variables ($var).

$ var=5
$ echo la valeur de la variable est $var
la valeur de la variable est 5
$ echo "la valeur de la variable est $var"
la valeur de la variable est 5

' ' Apostrophes

Les guillemets simples, ou apostrophes (' ') annule le sens de tous les caractères génériques sauf l'antislash.

$ echo '\$var'
\$var

4.3. Variables d'environnement

Variable shell $PS1

Le shell utilise toute une série de variables par exemple $PS1 (Prompt String 1) :

$ echo $PS1
\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$

Cette variable liée à la session connectée est une variable d’environnement fixée dans le fichier ~.bashrc

Variables d’environnement

Des variables d’environnement sont disponibles dans toutes les sessions. Par exemple PATH indique les chemins des exécutables :

$ echo $PATH
* /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

Pour afficher les variables d’environnement :

$ printenv

4.4. Variables spéciales

...

4.5. Portées des variables

Variables locales et globales

Il y a deux types de variables : les variables locales et les variables globales (exportées).

Les variables locales ne sont accessibles que sur le shell actif. Les variables exportées ou globales sont accessibles à la fois par le shell actif et par tous les processus fils lancés à partir de ce shell.

  • commande set
  • commande env
  • commande export une variable, -f pour une fonction
  • préceder de local la valorisation d'une variable dans une fonction afin d'en limiter sa portée.

4.6. Expansions de paramètres avec extraction

Extraction de sous-chaînes

On peut extraire des sous-chaînes de caractères :

A partir du début de la valeur de la variable selon la méthode suivante ${variable:debut:longueur}

$ echo ${PATH}
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/francois/.local/bin:/home/francois/bin
$ echo ${PATH:16:7}
usr/bin

Recherche de motifs

Les caractères génériques englobent d'autres caractères :

  • * signifie tout caractère
  • ? signifie un seul caractère
  • [Aa-Zz] correspond à une plage
  • {bin,sbin} corresond à une liste

Extraction du début et de la fin

Extraction du début retirant un motif selon ${variable#motif} :

$ echo ${PATH}
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/francois/.local/bin:/home/francois/bin
$ echo ${PATH#/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:}
/home/francois/.local/bin:/home/francois/bin
$ echo ${PATH#*sbin:}
/usr/sbin:/home/francois/.local/bin:/home/francois/bin
$ echo ${PATH##*sbin:}
/home/francois/.local/bin:/home/francois/bin

Extraction de la fin

Extraction de la fin retirant un motif selon ${variable%motif}

$ echo ${PATH}
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/francois/.local/bin:/home/francois/bin
$ echo ${PATH%/home/francois/.local/bin:/home/francois/bin}
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:
$ echo ${PATH%/home*}
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/francois/.local/bin:
$ echo ${PATH%%/home*}
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:

Remplacement sur motif

${variable/motif/remplacement}

$ echo ${PATH/$HOME/\~}
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:~/.local/bin:/home/francois/bin
$ echo ${PATH//$HOME/\~}
/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:~/.local/bin:~/bin

Compter les lettres

$ var=anticonstitutionnellement
$ echo Il y a ${#var} caractères dans cette variable
Il y a 25 caractères dans cette variable

4.7. Paramètres positionnels

Les paramètres positionnels représentent les éléments d'une commande en variables

On peut utiliser le script suivant pour illustrer les paramètres positionnels :

#! /bin/sh
# 06_affiche_arguments.sh
echo 0 : $0
if [ -n "$1"  ] ; then echo 1  : $1  ; fi
if [ -n "$2"  ] ; then echo 2  : $2  ; fi
if [ -n "$3"  ] ; then echo 3  : $3  ; fi
if [ -n "$4"  ] ; then echo 4  : $4  ; fi
if [ -n "$5"  ] ; then echo 5  : $5  ; fi
if [ -n "$6"  ] ; then echo 6  : $6  ; fi
if [ -n "$7"  ] ; then echo 7  : $7  ; fi
if [ -n "$8"  ] ; then echo 8  : $8  ; fi
if [ -n "$9"  ] ; then echo 9  : $9  ; fi
if [ -n "${10}" ] ; then echo 10 : ${10} ; fi

On obtient ceci :

$ ./06_affiche_arguments.sh un deux trois quatre zozo petzouille sept huit neuf 10

0 : ./06_affiche_arguments.sh
1 : un
2 : deux
3 : trois
4 : quatre
5 : zozo
6 : petzouille
7 : sept
8 : huit
9 : neuf
10 : 10

On peut optimiser les opérations avec la commande shift qui décale les paramètres vers la gauche (supprime le premier paramètre) :

#! /bin/sh
# 07_affiche_arguments_3.sh
while [ -n "$1" ] ; do
  echo $1
  shift
done

$#représente le nombre total de paramètres. On peut voir ceci :

#! /bin/sh
# 08_affiche_arguments_4.sh
while [ $# -ne 0 ]; do
  echo $1
  shift
done

On peut encore illustrer d'autres paramètres positionnels :

#!/bin/bash
# 09_affiche_arguments_spéciaux.sh
echo "Nom du script $0"
echo "Sremier paramètre $1"
echo "Second paramètre $2"
echo "Tous les paramètres $*"
echo "Tous les paramètres (préservant des espaces) $@"
echo "Nombre de paramètres $#"
echo "PID du shell $$"
echo "code de retour $?"
exit

4.8. Commandes en paramètres

kernel=$(uname -r)
echo $kernel

4.9. Expansions arithmétiques

$(( expression ))
declare -i variable

4.10. Tableaux

var=('valeur1' 'valeur2' 'valeur3')

5. Script rm amélioré

  • Reprise du script rm_secure.sh

On trouvera bon nombre d'exemples de scripts à télécharger sur la page http://www.blaess.fr/christophe/livres/scripts-shell-linux-et-unix/. Le script rm_secure.sh est situé dans le dossier exemples/ch02-Programmation_Shell/.

5.1. Commande rm

rm --help
Usage: rm [OPTION]... FILE...
Remove (unlink) the FILE(s).

  -f, --force           ignore nonexistent files and arguments, never prompt
  -i                    prompt before every removal
  -I                    prompt once before removing more than three files, or
                          when removing recursively; less intrusive than -i,
                          while still giving protection against most mistakes
      --interactive[=WHEN]  prompt according to WHEN: never, once (-I), or
                          always (-i); without WHEN, prompt always
      --one-file-system  when removing a hierarchy recursively, skip any
                          directory that is on a file system different from
                          that of the corresponding command line argument
      --no-preserve-root  do not treat '/' specially
      --preserve-root   do not remove '/' (default)
  -r, -R, --recursive   remove directories and their contents recursively
  -d, --dir             remove empty directories
  -v, --verbose         explain what is being done
      --help     display this help and exit
      --version  output version information and exit

By default, rm does not remove directories.  Use the --recursive (-r or -R)
option to remove each listed directory, too, along with all of its contents.

To remove a file whose name starts with a '-', for example '-foo',
use one of these commands:
  rm -- -foo

  rm ./-foo

5.2. Fonctionnalités du script

5.3. Description

  • Il s'agit d'une fonction à "sourcer" qui ajoute des fonctionnalités à la commande /bin/rm : une sorte de corbeille temporaire
  • Trois options supplémentaires et sept standards sont à interpréter
  • Des fichiers/dossiers sont à interpréter comme arguments possibles
  • Les fichiers/dossiers effacés sont placés dans une corbeille temporaire avant suppression.
  • Ces fichiers peuvent être listés et restaurés à l'endroit de l'éxécution de la commande.

Quels options peut-on ajouter ?

  • une vérification des droits sur le dossier temporaire
  • une option qui précise le point de restauration (approche par défaut, récupération emplacement original absolu)
  • une gestion des écrasements lors de la restauration (versionning, diff)
  • une gestion des écrasements de fichiers mis en corbeille

5.4. Concepts

Le script met en oeuvre les notions suivantes :

  • définition de variables
  • imbrications de boucles
  • boucle while; do command; done
  • Traitement d'options getopts
  • boucle case/esac ) ;;
  • condition if/then
  • tests [ ]
  • trap commande signal

5.5. Structure

Le Script exécute un traitement séquentiel :

  1. Déclarations de variables dont locales
  2. Traitement des options
  3. ...

5.6. Sourcer le script

En Bash :

source rm_secure.sh

5.7. Script automatique

Pour que le script démarre automatiquement au démarrage de la session de l'utilisateur :

  • ~/.bashrc

  • ~/.Bash_profile

6. Modèles de script Bash

6.1. Sélection d'instructions

Structure if-then-else

if condition_1
then
    commande_1
elif condition_2
then
    commande_2
else
    commande_n
fi
if condition ; then
    commande
fi

Conditions et tests

  • La condition peut-être n'importe quelle commande,
  • souvent la commande test représentée aussi par [ ].
  • Le code de retour est alors vérifié :
    • 0 : condition vraie
    • 1 : condition fausse

$ man test donne les arguments de la commande test.

Structure case-esac

case expression in
    motif_1 ) commande_1 ;;
    motif_2 ) commande_2 ;; ...
esac

L'expression indiquée à la suite du case est evaluée et son résultat est comparé aux différents motifs. En cas de correspondance avec le motif, une commande suivante est réalisée. Elle se termine par `;;``

Le motif peut comprendre des caractères génériques :

case
    *) ;;
    ?) ;;
    O* | o* | Y* | y*) ;;
    3.*) ;;
esac

Exercices

  1. Écrivez un script qui vérifie l'existence d'au moins un paramètre dans la commande.
  2. Écrivez un script qui vérifie que deux paramètres sont compris endéans un intervalle compris entre 0 et 100.
  3. Écrivez un script qui demande O/o/Oui/oui et N/n/Non/non dans toutes ses formes et qui rend la valeur.
  4. Écrivez un script qui ajoute un utilisateur existant dans un groupe .
  5. Écrivez un script qui crée un rapport sommaire sur les connexions erronées sur votre machine.
  6. Écrivez un script qui utilise les options de la commandetest (ou [ ]) pour décrire les fichiers qui lui sont passés en argument.

Modèle

Source : https://github.com/leonteale/pentestpackage/blob/master/BashScriptTemplate.sh

#!/bin/bash
##########################################################################
# Copyright: Leon Teale @leonteale http://leonteale.co.uk
##########################################################################
##########################################################################
# Program: <APPLICATION DESCRIPTION HERE>
##########################################################################
VERSION="0.0.1"; # <release>.<major change>.<minor change>
PROGNAME="<APPLICATION NAME>";
AUTHOR="You, you lucky so and so";

##########################################################################
## Pipeline:
## TODO:
##########################################################################

##########################################################################
# XXX: Coloured variables
##########################################################################
red=`echo -e "\033[31m"`
lcyan=`echo -e "\033[36m"`
yellow=`echo -e "\033[33m"`
green=`echo -e "\033[32m"`
blue=`echo -e "\033[34m"`
purple=`echo -e "\033[35m"`
normal=`echo -e "\033[m"`

##########################################################################
# XXX: Configuration
##########################################################################

declare -A EXIT_CODES

EXIT_CODES['unknown']=-1
EXIT_CODES['ok']=0
EXIT_CODES['generic']=1
EXIT_CODES['limit']=3
EXIT_CODES['missing']=5
EXIT_CODES['failure']=10

DEBUG=0
param=""

##########################################################################
# XXX: Help Functions
##########################################################################
show_usage() {
        echo -e """Web Application scanner using an array of different pre-made tools\n
        Usage: $0 <target>
        \t-h\t\tshows this help menu
        \t-v\t\tshows the version number and other misc info
        \t-D\t\tdisplays more verbose output for debugging purposes"""

        exit 1
        exit ${EXIT_CODES['ok']};
}

show_version() {
        echo "$PROGNAME version: $VERSION ($AUTHOR)";
        exit ${EXIT_CODES['ok']};
}

debug() {
        # Only print when in DEBUG mode
        if [[ $DEBUG == 1 ]]; then
                echo $1;
        fi
}

err() {
        echo "$@" 1>&2;
        exit ${EXIT_CODES['generic']};
}

##########################################################################
# XXX: Initialisation and menu
##########################################################################
if [ $# == 0 ] ; then
        show_usage;
fi

while getopts :vhx opt
do
  case $opt in
  v) show_version;;
  h) show_usage;;
  *)  echo "Unknown Option: -$OPTARG" >&2; exit 1;;
  esac
done



# Make sure we have all the parameters we need (if you need to force any parameters)
#if [[ -z "$param" ]]; then
#        err "This is a required parameter";
#fi

##########################################################################
# XXX: Kick off
##########################################################################
header() {
        clear
        echo -e """
----------------------------------
 $PROGNAME v$VERSION $AUTHOR
----------------------------------\n"""
}

main() {

#start coding here
  echo "start coding here"

}

header
main "$@"

debug $param;

Annexe Références et exemples

Annexe : Exercices de scripts sur les noms de fichiers

On vous présente un cas où nous sommes invités à renommer des fichiers ayant l'extension tar.gz en tar.gz.old et inversément.

Pour réaliser cet exercice nous avons besoin d'un certain nombre de fichiers. Une idée serait d'utiliser la commande touch. Supposons qu'il faille créer 100 fichiers numérotés dans un dossier temporaire.

Cas : vider et créer un dossier temporaire de travail

Pour vider et créer un dossier temporaire de travail, on pourrait proposer ceci d'illustrer la fonction conditionnelle if condition ; then commandes; else commandes; fi :

#! /bin/sh
# 01_tmp.sh
dir="${HOME}/tmp/"
if [ -d ${dir} ] ; then
    rm -rf ${dir}
    echo "Le dossier de travail ${dir} existe et il est effacé"
fi    
mkdir ${dir}
echo "Le dossier de travail ${dir} est créé"

Cas : créer des fichiers à la volée

Pour créer des fichiers, on peut utilser la commande touch :

TOUCH(1)                  BSD General Commands Manual                 TOUCH(1)

NAME
     touch -- change file access and modification times

SYNOPSIS
     touch [-A [-][[hh]mm]SS] [-acfhm] [-r file] [-t [[CC]YY]MMDDhhmm[.SS]] file ...

DESCRIPTION
     The touch utility sets the modification and access times of files.  If any file does not
     exist, it is created with default permissions.

     By default, touch changes both modification and access times.  The -a and -m flags may be used
     to select the access time or the modification time individually.  Selecting both is equivalent
     to the default.  By default, the timestamps are set to the current time.  The -t flag explic-
     itly specifies a different time, and the -r flag specifies to set the times those of the spec-
     ified file.  The -A flag adjusts the values by a specified amount.

Pour faire une certaine chose tant qu'une condition est remplie on utilise une boucle while condition ; do commandes ; done

#! /bin/sh
# 02_creation_fichiers0.sh
dir="${HOME}/tmp/"
i=0
while [ $i -lt 100 ] ; do
    touch ${dir}fic$i.tar.gz
    echo "Création de ${dir}fic$i.tar.gz"
    i=$[$i+1]
done

De manière peut-être plus élégante avec l’instruction for ((initial;condition;action)); do commandes; done :

#!/bin/sh
# 03_creation_fichiers.sh
dir="${HOME}/tmp/"
i=0
#for ((initial;condition;action))
for ((i=0;i<100;i=i+1)); do
    touch ${dir}fic$i.tar.gz
    echo "Création de ${dir}fic$i.tar.gz"
done

Cas : renommage

Cas : renommage de *.tar.gz en *.tar.gz.old

Supposons maintenant que nous souhaitions renommer tous nos fichiers *.tar.gz en *.tar.gz.old, nous taperons le script suivant :

#!/bin/sh
# 04_renommage.sh
#x prend chacune des valeurs possibles correspondant au motif : *.tar.gz
dir="${HOME}/tmp/"
for x in ${dir}*.tar.gz ; do
  # tous les fichiers $x sont renommés $x.old
  echo "$x -> $x.old"
  mv "$x" "$x.old"
  # on finit notre boucle
done

Cas : renommage inverse

Cas : renommage inverse *.tar.gz.old *.gz.old

Voici le script inverse, c’est sans compter sur d’autres outils pour d’autres situations :

#!/bin/sh
# 05_denommage.sh
#x prend chacune des valeurs possibles correspondant au motif : *.tar.gz.old
dir="${HOME}/tmp/"
for x in ${dir}*.tar.gz.old ; do
  # tous les fichiers $x sont renommés $x sans le .old
  echo "$x -> ${x%.old}"
  mv $x ${x%.old}
  # on finit notre boucle
done

Cas : script extraction_serveurs.sh

On peut réaliser l'exercice extraction_serveurs.sh

results matching ""

    No results matching ""