Initiation aux commandes Bash


Bash acronyme de Bourne Again Shell est un interpréteur de commandes développé en 1989 par Brian Fox. Au début de sa création, ce petit logiciel permettait de rendre exécutable les programes GNU installé sur un système. Aujourd'hui il comporte de nombreuses extensions et il existe des alternatives comme CSH, KSH, ZSH, ou même Oh My ZSH.

Guide avancé :

Voir les directives chargé par le terminal :

stty -a
env

Utilisation des variables

v="pain"
# Variable statique:
readonly p=22
f=20
echo "Du ${var} à ${p}0,$(($p-$f))0 euros!"
$ Du pain à 220,20 euros!
  • Variable par défaut:
var="${1:-default}"
echo "var = $var"
$ ./script.sh param1
$ var = param1
$ ./script.sh
$ var = default
  • Taille d'une chaine
string="chaine"
echo ${#string}

Concaténation

a="a"
b="b"
x="${a} ${b}"
echo ${x}
$ a b

Utiliser des variables d'environnements et arguments

  • $PATH → Chemin courant
  • $0, $1, $2, … → numéro de l'arguments
  • $# → nb d'arguments
  • $* → tous les arguments

Executer une commande externe

cmd=$(pwd)
echo $cmd
$ /home/utilisateur

Transformer une chaîne en tableau

  • String to array in bash :
var="a b c d"
var=($var)
echo "Nombre de cases : ${#list[@]}"
Nombre de cases : 4
  • Supprimer une case et lister toutes ces valeurs pour la transformer en chaine :
shift 1
for domain in "$@"; do
    domains="${domains:+${domains} }${domain}"
done
  • Utiliser une boucle
declare -A DATES
 
for i in 1 2 3 4; do
  DATES[$i]=$( date +"%Y%m%d" --date="$i days ago" )
done
 
for i in "${DATES[@]}" ; do echo "$i"; done

Découpage d'une chaine

⇒ Supprime ce qui est avant le dernier terme rencontré :

var="test.tst.ts.t"
echo ${var##*.}
$ t

⇒ Supprime ce qui est avant le premier therme rencontré :

var="test.tst.ts.t"
echo ${var#*.}
$ tst.ts.t

⇒ Supprime ce qui est après le dernier therme rencontré :

var="test.tst.ts.t"
echo ${var%.*}
$ test.tst.ts

⇒ Supprime ce qui est après le premier therme rencontré :

var="test.tst.ts.t"
echo ${var%%.*}
$ test

⇒ Sélectionner une portion d'une chaine !

var="test.tst.ts.t"
echo ${var:5:3}"
$ tst

Substituer (trouver et remplacer) un mot

var="bonjour le monde!"
echo ${var/bonjour/aurevoir}
$ aurevoir le monde!

Les conditions

En pratique c'est la commande test qui sera appelé lorsque l'on utilise ces caractères “[” et “]”

x=true
if [ $x ] || [ "$x" = "var_inutile" ]; then
        echo true
elif [ "$x" = "autre" ]; then
        echo false
else
        echo "else"
fi
 
if ss -tr |grep microsoft-ds 1>/dev/null ; then
  echo utilisateur connecté
else
  echo utilisateur deconnecté
fi

Sur une seule ligne :

x=true
[ $x ]; echo $?;

Si 0 = vrai. Si 1 = faux (celà signifie généralement qu'il y a une erreur).

  • Si l'on utilise l'opérateur -a (and) :
a=true
b=false
[ $a -a $b ]; echo $?;
$ 0
  • Si l'on utilise l'opérateur -o (or) :
a=true
b=false
[ $a -o $b ]; echo $?;
$ 0
Lors d'une comparaison avec une chaine renseigné dans une variable, il faut faire “$chaine”.

Opérateurs de comparaisons

un man test permet de voir la liste des comparaison supporté

  • -e fichier → vrai si fichier existe
  • -d fichier → vrai si fichier est répertoire
  • -L fichier → vrai si fichier est un lien symbolique
  • -r fichier → vrai si fichier est lisible (en écriture)
  • -w fichier → vrais si fichier est modifiable (w)
  • -x fichier → vrai si fichier est exécutable -w)
  • -s fichier → vrai si le fichier est non vide
  • file1 -nt file2 → vrai si file1 est plus récent que file2
  • file1 -ot file2 → vrai si file1 est plus ancien que file2

Opération sur les chaines

  • -z “chaine” → vrai si la chaine est vide
  • -n “chaine” → vrai si la chaine est non vide
  • “chaine1” = “chaine2” → vrai si les deux chaine sont égales
  • “chaine1” != “chaine2” → vrai si les deux chaines sont différentes

Opérateur de comparaison numérique

  • $num1 -eq $num2 → égalité
  • $num1 -ne $num2 → inégalité
  • $num1 -lt $num2 → inférieur
  • $num1 -le $num2 → inférieur ou égal
  • $num1 -gt $num2 → supérieur
  • $num1 -ge $num2 → supérieur ou égal

Les boucles

La boucle “for” est rudimentaire. C'est à dire qu'il faut obligatoirement un tableau pour qu'elles puissent fonctionner.

⇒ For :

# Lis un tableau :
 
a=(un deux trois quatre)
b=5
 
for x in ${a[@]}
do
        echo x= $x
done
 
# Simple boucle avec un timer :
 
for sec in $(req 1 5) ; do
  echo $sec
  sleep 1
done

⇒ while :

while [ ! -f "fichier.txt" ]
do
	sleep 1;
done
echo fichier trouvé!

ou ainsi

cat plusieurs-lignes.txt | while red mot ; do echo $mot ; done

Structures de contrôles

  • Switch
case $1 in
        start)
                echo start! ;;
        stop|restart)
                echo stop ou restart! ;;
        *)
                echo autre.. ?
esac

Les fonctions

fonc() {
	echo mon parametre : $1
}
 
fonc coucou
$ mon parametre : coucou

Les codes couleurs

  • Utiliser la couleur rouge :
echo -e "\033[31m ROUGE \033[0m"

Regex

  • Tester si un mot est inclu dans une chaine :
chaine="bruno est present"
 
if [[ "$chaine" =~ "present" ]]
then
    echo "le mot est bien présent dans la chaine!
fi

Inclure un tableau dans un fichier

Admettons que nous avons ce fichier :

boot.html
#__SCANS_ITEMS__/

Et que nous avons ce script :

items=$(ls -1)
items=($items)
awk -v r="$items" '{gsub(/#__SCANS_ITEMS__/,r)}1' boot.html > boot.html.tmp
mv boot.html.tmp boot.html

En l'exécutant, il va substituer les valeurs inclus dans items par la ligne indiqué. Ici #SCANS_ITEMS/.

Variables d'environnement Bash

On peut les lister avec la commande suivante :

set

Ou ajouter des options pour modifier le comportement de bash

  • -a → Exporte les variables qui ont été modifié ou créé maintenant.
  • -e → Termine le script s'il y a une erreur.
  • -f → Désactive le caractère “*” : https://gist.github.com/codeforkjeff/79dda02f162ee1f350d9
  • -m → Active la gestion des job (dans le cas d'usage des subshell).
  • -n → N'execute pas les commandes.
  • -t → Termine le script après avoir lu et executé une commande.
  • -v → Mode verbose sans les arguments.
  • -x → Mode verbose avec les arguments.
  • - → Désactive les options -x et -v.

e

Quelques commandes supplémentaires

  • Écrire dans un fichier :
cat > /tmp/exemple.txt <<EOF
Le contenu de ce fichier
est sur plusieurs lignes.
:)
EOF
  • dirname fichier = nom de répertoire de fichiers
  • basename fichier = nom du fichier
  • echo -n = évite le retour à la ligne
  • echo -e = execute les méta caractères tel que le retour chariot “\n” ou \e[1em (couleur)
  • reset = idem au paquet clair ?
  • Saisir un mot de passe au clavier :
read -p "Entrez votre mot de passe : " -s pass
  • Lire un texte depuis stdin :
script.sh
#!/bin/bash
cat /dev/stdin |grep maison
$ cat nombreuses-lignes.txt |script.sh
maison
maisonnette

Plus d'infos à ce sujet : http://lipn.univ-paris13.fr/~cerin/SE/S2SE_01_LectureFichiersShell2.html

  • Lancer une commande en tâche de fond grâce au caractère & :
sleep 20 &

Celui-ci peut être mis en pause avec les touches : Ctrl+z

  • Compter le nombres de lignes depuis une sortie (ou depuis un fichier) :
cat /etc/passwd | wc -l
wc -l /etc/passwd
  • Supprimer des lignes en doubles depuis un fichier :
uniq <fichier> -u
  • Décommenter une phrase :
sed 's|# \(.*blue.*\)|\1|' input.txt
  • Remplacer une phrase depuis une ligne précise :
sed -i "307s/.*/\tdisableThirdPartyRequests: true,/" input.txt
  • Faire un filtre sur un mot :
grep -e 'postgres' /etc/postgres       # Retournera que la ligne contenant postgres
grep -v 'postgres' /etc/postgres       # Retournera tout sauf la ligne contenant postgres
  • Récupérer le contenu d'un fichier entre les lignes 15 à 20 :
cat /etc/passwd | head -n 20 | tail -n 5
  • Récupérer le contenu de la 1ère et la dernière collone :
awk -F ":" '{ print $1 $NF }' /etc/passwd
  • Récupérer un contenu spécifique avec des critères de sélections :
awk 'BEGIN { FS = ":"
             printf ("\nUser id\t\tShell\n\n") }
           { printf ("%s\t\t%s\n", $1, $7) }
     END   { printf "\nTotal numer of user ids = %d\n", NR } ' /etc/passwd
  • Nombre total de ligne (comme avec wc -l)
awk 'END { print "Total ligne : " NR }' /etc/passwd
  • Compter des données :
awk ' BEGIN { FS = ","  }
      { 
         if ( NR == 1 || NR == 4 || NR == 5 )
              printf ("%s,%s,%s,%s\n", $1, $2, $3, $4) 
         else {
               sum2 += $2
               sum3 += $3
               sum4 += $4
               printf ("%s,%6d,%6d,%6d\n", $1, $2, $3, $4) }
      }
      END    { printf ("Totals,%6d,%6d,%6d\n", sum2, sum3, sum4) } 
' <<EOF
Expenditure,2012,2013,2014
Advertising,200015,233912,189928
Bank charges, 23029, 26667, 34990
***********,****,****,****
Expenditure,2015,2016,2017
Bank charges, 23029, 26667, 34990
Boarding and Lodging,237899,453326,356625
EOF
  • Gestion des sorties EOF
echo "debut"
 
cat <<EOF >log.txt 
        Status of backup as on $(date)
        Where ?? -> $HOME
EOF
 
echo "fin"

* Jouer avec les couleurs

https://misc.flogisoft.com/bash/tip_colors_and_formatting

  • Fermer le stdin d'un script entier :
exec <&-
  • Dernière modification: 2020/04/08 21:56