Liens
Début de fichier
|
# spécifie quel shell doit être utilisé
#!/usr/bin/bash
set -e
set -o pipefail
set -u
wd="$(dirname "$(realpath "$0")")"
|
|
# arrête le script si une commande (ligne complète) échoue (retourne une valeur différente de true)
set -e
# désactiver l'option
set +e
# arrête le script si une commande (dans un pipe) retourne une valeur différente de true
set -o pipefail
# arrête le script si une variable non-initialisée est utilisée
set -u
|
Debug
Afficher des informations au fil de l'éxecution du script
|
# lancer le script en mode debug
bash -x script.sh
# modifier la premier ligne du script pour l'éxecuter en mode debug
#!/bin/bash -xv
|
Debug a Shell Script Under Linux
Lire les entrées du clavier
Lis le clavier jusqu'à ce que la touche entrée soit pressée.
|
read input
# avec du texte
read -r -p 'Entrée : ' input
# -r : \ n'agit pas comme un caractère d'espacement
echo $input
# sans afficher la saisie: pour les mots de passe
read -r -s -p 'Password : ' password
echo # saut de ligne car l'appuie sur entrée n'a pas été pris en compte
|
|
echo Titre
PS3='question? '
select choix in \
"Premier choix" \
"Second choix" \
"Quitter"
do
echo Vous avez choisi $choix
case $REPLY in
1) echo choix n°$REPLY;;
2) echo choix n°$REPLY;;
3) exit 0;;
*) echo $REPLY: choix invalide;;
esac
echo # saut de ligne
done
|
Arguments passés au script
$*
liste des arguments séparés par des espaces. Attention aux arguments contenant des espaces
"$@"
liste des arguments entourés par des guillemets et séparés par des espaces
$1 ... $9 ${10}
arguments de position, utiliser les accolades à partir de 10
$#
nombre d'arguments
|
# entrée: "fichier 1.jpg" fichier\ 2.jpg
for file in "$@" ; do ... ; done
# fichier\ 1.jpg
# fichier\ 2.jpg
# $* pose problème avec les arguments contenant des espaces car le séparateur d'argument est aussi espace
# il faut donc remplacer toutes les occurrences d'espaces dans les arguments
${*// /\\ } # fichier\ 1.jpg fichier\ 2.jpg
ARGS=("$@")
"${ARGS[@]}" # tous les arguments
"${ARGS[0]}" # premier argument
|
|
OPTS=$(getopt -o vhn -l verbose,help,dry-run -n 'parse-options' -- "$@")
# -o short option name
# -l long option name
# -n name used when it reports errors
# -- indicate the ends of the options
# option format:
# h no-value
# h: mandatory with value
# h:: optinal with value
if [ $? != 0 ] ; then echo "Failed parsing options." >&2 ; exit 1 ; fi
eval set -- "$OPTS"
VERBOSE=false
HELP=false
DRY_RUN=false
while true
do
case "$1" in
-v | --verbose ) VERBOSE=true; shift ;;
-h | --help ) HELP=true; shift ;;
-n | --dry-run ) DRY_RUN=true; shift ;;
-- ) shift; break ;;
* ) break ;;
esac
done
echo HELP=$HELP
echo STACK_SIZE=$STACK_SIZE
if $HELP
then
usage
exit 0
fi
|
test des arguments et usage
|
usage() {
echo "$(basename $0) arg1"
echo ""
echo "arg1: ..."
}
# si aucun argument n'est renseigné ou si le premier argument est vide, on appel usage et on quitte
if [[ $# == 0 ]] || [[ -z $1 ]]; then
usage
exit 1
fi
|
shift
Permet de consommer le premier argument et de décaler tous les autres
|
if [[ $1 == '--mon-option' ]]; then
# shift permet de décaler tous les arguments d'une position vers la gauche: $2 → $1, $3 → $3, etc
shift
fi
# si $1 == --mon-option, $2 remplacera $1 pour l'appel à MaFonction
MaFonction $1
|
Redirections
- 0 is stdin, l'entrée standard
- 1 is stdout, la sortie standard
- 2 is stderr, les erreurs
|
# redirige stdout vers un fichier, il est créé s'il n'existe pas, sinon il est écrasé
commande > fichier
# équivalent à :
commande 1> fichier
# commande >> fichier pour ajouter à la suite du fichier
# redirige stderr vers un fichier
commande 2> fichier
# redirige stderr vers stdout
commande 2>&1
# redirige stdout et stderr vers file.log
# redirige stdout vers file.log, puis stderr vers stdout donc vers file.log
commande >file.log 2>&1
# redirige stderr vers le terminal et stdout vers un fichier
# redirige stderr vers stdout donc vers le terminal, puis stdout vers file.log
commande 2>&1 >file.log
# masque stdout et stderr
commande &> /dev/null
commande >/dev/null 2>&1
# redirige stderr vers stdout (terminal) et écrit stdout (et stderr) vers un fichier
commande 2>&1 | tee fichier
# tee -a fichier pour ajouter à la suite du fichier
# with multiple commands
{
echo "1"
echo "2"
} 2>&1 | tee -a log/$(date '+%Y-%m-%d').log
# affiche la sortie de commande dans la console et l'écrit aussi dans fichier. Utile pour conserver les couleurs.
script -q -c 'commande' fichier
|
Variables
|
# affectation d'une variable, attention pas d'espaces autour du =
ma_variable="valeur"
# affichage du contenu d'une variable
echo $ma_variable # valeur
echo $ma_variable1 #
echo ${ma_variable}1 # valeur1
# par défaut toutes les variables sont globales
# locale permet de définir une variable locale
locale ma_variable="valeur"
# variable readonly
readonly my_ro_var='value'
# suppression d'une variable
unset ma_variable
# affichage de l'ensemble des variables définies dans le shell
set
|
|
Par défaut, le scope des variables est globale. |
|
Les noms de variables ne peuvent pas contenir de - |
Variables spéciales
$$ |
PID du shell courant
|
$! |
PID du dernier travail lancé en arrière plan
|
$? |
code retour de la dernière commande
|
Variables d'environnement
$HOME |
chemin du répertoire personnel de l'utilisateur
|
$PATH |
liste des chemins de recherche des commandes exécutables
|
$PPID |
PID du processus père du shell
|
$PWD |
chemin du répertoire courant
|
$RANDOM |
nombre entier aléatoire compris entre 0 et 32767
|
|
# Afficher toutes les variables d'environnement
printenv
|
Définies dans les fichiers suivants:
- /etc/profile
- /etc/profile.d/*
- $HOME/.zshrc
Stocker le résultat d'une commande
|
currentpath=$(pwd)
cd "$currentpath"
|
String vs entier
Par défaut une variable contient un string. Mais on peut déclarer une variable comme un entier.
|
v=1 # 1
v+=1 # 11
# declare v comme un entier
declare -i v
v=1 # 1
v+=1 # 2
|
For
|
listeDeChiffres="1 2 3 4 5"
for chiffre in $listeDeChiffres
do
echo chiffre : $chiffre
done
# équivalent sur une seule ligne
for chiffre in $listeDeChiffres ; do echo chiffre : $chiffre ; done
for lettre in {a..z}
# i à 5 puis de 10 à 50 et enfin à 100 et 110
for i in 5 {10..50} 100 110
# i de 10 à 50 avec un incrément de 2
for i in {10..50..2}
# i de 1 à 5 avec un incrément de 1
for (( c=1; c<=5; c++ ))
# boucle infinie
for (( ; ; ))
|
While
|
# tant que name est vide on demande sa saisie
while [ -z $name ]
do
read -p 'Name : ' name
done
# tant que firefox tourne
while pgrep firefox >/dev/null
do
read -p 'Fermez Firefox avant de continuer.' askclosefirefoxinput
done
# lister les dossiers par ordre décroissant de création
ls -t | while read element
do
[[ -d $element ]] || continue
echo $element
done
# for element in $(ls -t) ne permet pas gérer les noms avec espaces
# read file names in a file and delete them
while IFS= read -r f; do [ -f "$f" ] && rm -f "$f"; done < list.txt
|
if / else
|
if (expression); then
echo 1
elif ! (expression); then
echo 2
else
echo 3
fi
# en une ligne
if [ expression ]; then echo 1; echo 2; else echo 3; fi
|
[[ ]]
|
# if expression is true then execute commande
[[ expression ]] && command
# if expression is false then execute commande
[[ expression ]] || command
|
Booleans
|
var1=false
if $var1
if [ $var1 = true ]
if [[ $var1 = true ]]
|
Strings
|
if [[ $1 == $2 ]] # vrai si le string contenu dans $1 est le même que celui dans $2
if [[ $1 != $2 ]] # vrai si le string contenu dans $1 n'est pas le même que celui dans $2
|
|
Do not use the ${var} form to call the variable, use $var instead. |
|
# utilisation de *: startwith, endwith, contains
if [[ $1 == XXX* ]] # vrai si $1 commence par XXX
if [[ $1 == *XXX ]] # vrai si $1 se termine par XXX
if [[ $1 == *XXX* ]] # vrai si $1 contient XXX
if [[ $1 == *'XXX YYY'* ]] # vrai si $1 contient XXX YYY
# expression rationnelle
if [[ $1 =~ [0-9][0-9]\.jpg$ ]] # vrai si $1 respecte l'expression rationnelle
if [[ $mon_texte =~ http://[a-zA-Z0-9._/]+\.jpg ]]
then
echo "OK: ${BASH_REMATCH}"
else
echo "KO"
fi
# groupes. Ex: 20160530 → 2016-05-30
if [[ $mon_texte =~ ([0-9]{4})([0-9]{2})([0-9]{2}) ]]; then
echo "${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]}"
fi
|
|
Escape the following characters ( ) . |
Entiers
|
if [[ $1 -gt $2 ]] # vrai si l'entier contenu dans $1 est plus grand que celui dans $2
if [[ $1 -lt $2 ]] # vrai si l'entier contenu dans $1 est plus petit que celui dans $2
if [[ $1 -ge $2 ]] # vrai si l'entier contenu dans $1 est plus grand ou égual à celui dans $2
if [[ $1 -le $2 ]] # vrai si l'entier contenu dans $1 est plus petit ou égual à celui dans $2
if [[ $1 -eq $2 ]] # vrai si l'entier contenu dans $1 est égual à celui dans $2
if [[ $1 -ne $2 ]] # vrai si l'entier contenu dans $1 n'est pas égual à celui dans $2
|
|
Il est préférable d'utiliser la forme (( ))
|
if (($1>$2))
| |
Opérateurs ET, OU
|
if [[ $1 -gt $2 && $1 -lt 100 || $1 -eq 0 ]]
if [[ $1 -gt $2 && ($1 -lt 100 || $1 -eq 0) ]] # avec des parenthèses
|
Fichiers, dossiers
|
if [[ -e $1 ]] # vrai si $1 existe : fichier, répertoire ou lien pointant vers un fichier ou répertoire existant
if [[ -f $1 ]] # vrai si $1 est un fichier ou lien pointant vers un fichier existant
if [[ -d $1 ]] # vrai si $1 est un répertoire
if [[ -L $1 ]] # vrai si $1 est un lien, même si le lien ne pointe pas vers un fichier ou répertoire existant
if [[ -r $1 ]] # vrai si $1 est accessible en lecture
if [[ -w $1 ]] # vrai si $1 est accessible en écriture
if [[ -x $1 ]] # vrai si $1 est exécutable
|
Différences entre [ ] et [[ ]]
- [[ ]] ne fonctionne qu'avec Bash et Korn shell.
- Avec [[ ]], il n'est pas nécessaire d'entourer les variables de quotes
- Avec [[ ]], les parenthèses n'ont pas besoin d'être échappées
La commande test ou [ ]
|
if test -e "$1" # vrai si $1 existe : fichier, répertoire ou lien
if [ -f "$1" ] # vrai si $1 est un fichier
if [ -d "$1" ] # vrai si $1 est un répertoire
if [ -r "$1" ] # vrai si $1 est accessible en lecture
if [ -x "$1" ] # vrai si $1 est éxécutable
if [ ! ] # opérateur de négation
if [ -n "$1" ] # vrai si $1 est de longueur supérieur à 0
if [ -z "$1" ] # vrai si $1 est de longeur 0, ex: pas d'argument
if [ e1 -a e2 ] # vrai si e1 ET e2 sont vrai
if [ e1 ] && [ e2 ] # il est plutôt conseillé d'utiliser cette forme
if [ e1 -o e2 ] # vrai si e1 OU e2 sont vrai
if [ e1 ] || [ e2 ] # il est plutôt conseillé d'utiliser cette forme
if [ \(e1 -o e2\) -a e3 ] # parenthèses
if { [ e1 ] || [ e2 ] ; } && [ e3 ] # il est plutôt conseillé d'utiliser cette forme
|
Permet de faire des comparaisons d'entiers
|
if (( $1 > 10 ))
if (( $1 < 20 ))
if (( $1 == 15 ))
if (( $1 != 15 ))
if (( $1 % 100 == 0 ))
echo $(( 1 == 1 )) # vrai : 1, faux : 0
|
Mais aussi des opérations sur les entiers
|
echo $(( $1 += 1 )) # ajoute 1 à $1
echo $(( i += 1 )) # ajoute 1 à i
# nombre aléatoire entre 0 et 9.
echo $((RANDOM % 10))
# % : modulo, RANDOM entier entre 0 et 32767
|
Nombres commençant par 0
Les nombres commençant par 0 sont traités en octal
|
echo $((08+1))
# bash: ((: 08 : valeur trop grande pour la base (le symbole erroné est "08")
# bash: 08: value too great for base (error token is "08")
# zsh: ok
# Forcer le calcul en base 10 :
echo $((10#08+1))
v=08
echo $((10#$v+1))
|
|
# Supprimer les 0 un par un :
while [[ $v = 0* ]]; do v=${v#0}; done
# Supprimer tous les 0 :
v=${v/*(0)/}
|
String
Exécuter une commande
|
cmd="ls"
# exécute ls et affiche le résultat
eval ${cmd}
# exécute ls et tente d'exécuter le premier élément (fichier ou dossier) comme une commande
$(${cmd})
# command not found: fichier1
# exécute ls et stocke le résultat dans cmd2
cmd2=$(${cmd})
echo ${cmd2}
|
Fichiers, dossiers et chemins
|
file="/path/filename.ext"
# extraire le nom du fichier : filename.ext
filename=${file##*/}
filename=basename "$file"
# extraire le nom du fichier sans l'extension : filename
${filename%.*}
# extraire l'extension : ext
${filename##*.}
# extraire le chemin : /path
${file%/*}
# obtenir le chemin absolu à partir d'un chemin relatif ou d'un lien symbolique
readlink -f fichier
# concatène le chemin courant avec le nom du fichier: /chemin/courant/fichier
|
Concaténation
|
mot1="une"
mot21="bon"
mot22="ne"
echo "$mot1 $mot21$mot22 concaténation" # une bonne concaténation
echo $mot1 $mot21"ne concaténation"
mot1="${mot1} bonne concaténation"
|
Longueur d'un string
|
# avec une variable
longueur=${#MonString}
# longueur +1
echo "AAA" | wc -c
# fonctionne avec variables et cosntantes
expr lenght "AAA"
|
Index, position du premier caractère correspondant
|
expr index $string $substring
# stringZ=abcABC123ABCabc
echo $(expr index "$stringZ" 1c) # 3 (c in position 3 matches before 1).
|
|
${string:position:length} ou expr substr $string $position $length
# Extracts $substring at beginning of $string, where $substring is a regular expression.
expr match "$string" '\($substring\)' ou expr "$string" : '\($substring\)'
# Extracts $substring at end of $string, where $substring is a regular expression.
expr match "$string" '.*\($substring\)' ou expr "$string" : '.*\($substring\)'
# stringZ=abcABC123ABCabc
# 123456789......
echo ${stringZ:7} # 23ABCabc # tout à partir du 7ème
echo ${stringZ:7:3} # 23A # 3 caractères à partir du 7ème
echo ${stringZ: -4} # Cabc # les 4 derniers
echo ${stringZ:0:-4} # abcABC123AB # tout sauf les 4 derniers
echo $(expr substr $stringZ 4 3) # ABC
echo $(expr "$stringZ" : '\(.......\)') # abcABC1
echo $(expr match "$stringZ" '\(.[b-c]*[A-Z]..[0-9]\)') # abcABC1
echo $(expr match "$stringZ" '.*\([A-C][A-C][A-C][a-c]*\)') # ABCabc
|
|
?, +, {} et | doivent être utilisés avec un backslash : \? \+ \{\} \| |
|
L'utilisation des parenthèses avec expr match permet de renvoyer un string, sinon un entier est renvoyé égal au nombre de caractères qui correspondent. |
Suppression d'un sous-string
|
${string#substring} # Supprimer le plus court sous-string en commençant par le début.
${string##substring} # Supprimer le plus long sous-string en commençant par le début.
${string%substring} # Supprimer le plus court sous-string en commençant par la fin.
${string%%substring} # Supprimer le plus long sous-string en commençant par la fin.
stringZ=abcABC123ABCabc
# |----| shortest
# |----------| longest
echo ${stringZ#a*C} # 123ABCabc # Supprime au début la plus courte correspondance entre 'a' et 'C'.
echo ${stringZ##a*C} # abc # Supprime au début la plus longue correspondance entre 'a' et 'C'.
echo ${stringZ%A*c} # abcABC123 # Supprime à la fin la plus courte correspondance entre 'A' et 'c'.
echo ${stringZ%%A*c} # abc # Supprime à la fin la plus longue correspondance entre 'A' et 'c'.
echo ${stringZ%a*C} # abcABC123ABCabc # Pas de correspondance trouvée par la fin.
echo ${stringZ#*C} # 123ABCabc # Supprime tous le début jusqu'au premier 'C'.
echo ${stringZ##*C} # abc # Supprime tous le début jusqu'au dernier 'C'.
echo ${stringZ%C*} # 123ABCabc # Supprime toute la fin à partir du dernier 'C'.
echo ${stringZ%%C*} # abc # Supprime toute la fin à partir du premier 'C'.
|
Remplacement d'un sous-string
|
${string/substring/replacement} # Replace first match of $substring with $replacement.
${string//substring/replacement} # Replace all matches of $substring with $replacement.
${string/#substring/replacement} # Remplace si $string commence par $substring
${string/%substring/replacement} # Remplace si $string se termine par $substring
stringZ=abcABC123ABCabc
echo ${stringZ/abc/xyz} # xyzABC123ABCabc # Replaces first match of 'abc' with 'xyz'.
echo ${stringZ//abc/xyz} # xyzABC123ABCxyz # Replaces all matches of 'abc' with 'xyz'.
echo ${stringZ/#abc/XYZ} # XYZABC123ABCabc # Remplace 'abc' avec 'XYZ' au début.
echo ${stringZ/%abc/XYZ} # abcABC123ABCXYZ # Remplace 'abc' avec 'XYZ' à la fin.
echo ${stringZ//\\//} # Remplace tous les '\' par '/'.
|
Permet de construire une liste d'argument.
|
# par défaut xrags appelle echo avec la liste des arguments
echo 1 2 3 4 | xargs # 1 2 3 4
echo 1 2 3 4 | xargs cmd # cmd 1 2 3 4
echo 1 2 3 4 | xargs -n 1 cmd # cmd 1; cmd 2; ...
find . -iname "*.mp3" -print0 | xargs -0 -I mp3file mplayer mp3file
# -print0 et -0 pour gérer les espaces dans les arguments (noms de fichier)
# -I permet de donner un nom à l’argument et de l'utiliser par la suite
# supprimer tous les fichiers sauf les 3 plus récents
ls -t "${MyPath}" | tail -n +3 | xargs -0 rm -f --
|
|
-0 Gère les chemins avec des espaces. |
Tableaux / Arrays
Par défaut toutes les valeurs du tableau sont vide. Il n'est pas nécessaire de l'initialiser. Sa taille n'est pas définie.
|
monTableau=() # déclaration d'un tableau vide
monTableau=(valeur0 valeur1 valeur2) # initialisation des valeur 0,1 et 2
monTableau=([0]=valeur0 [10]=valeur10) # initialisation des valeurs 0 et 10
echo ${monTableau[10]} # valeur10
monTableau[5]=valeur5 # changement de la valeur 5
# ajout de valeurX à la fin du tableau
monTableau+=('valeurX')
# nombre d'éléments du tableau
echo ${#monTableau[@]}
# tester si le tableau contient un élément
if [[ " ${monTableau[@]} " =~ " ${value} " ]]; then
# ...
fi
# parcourir le tableau, utiliser les double quotes pour les éléments contenant des espaces
for element in "${monTableau[@]}"
do
echo $element
continue
done
# afficher le contenu du tableau avec un retour à la ligne après chaque élément
printf "%s\n" "${monTableau[@]}"
# utiliser le contenu du tableau dans une commande
IFS=§ # changer l'internal field separator pour gérer les espaces dans les éléments du tableau
rm -f ${monTableau[@]}
# stocker le résultat d'une commande dans un tableau
IFS=$'\n' read -r -d '' -a my_array \
< <(find '/folder' -maxdepth 1 -type d -printf "%f\n" && printf '\0')
|
Associative arrays / Hash tables / Dictionnaires
|
declare -A map
map[key1]="Value 1"
echo ${map[key1]}
# déclaration en une ligne
declare -A map=( [key1]="Value 1" )
for key in "${!map[@]}"; do
echo "$key - ${map[$key]}"
done
|
|
# stop le script en cas d'erreur
set -e
# ouverture du trap et définition de la commande à exécuter si le signal EXIT est capturé
trap 'echo 333' EXIT
echo 111
# l’exécution de 'commande inconnue' va créer une erreur et le script va s'arrêter (set -e) en lançant le signal EXIT
# le signal EXIT sera capturé par le trap et la commande associée au trap sera exécutée
'commande inconnue'
echo 222
# fermeture du trap, si le signal EXIT est lancé après la fermeture il ne sera pas capturé
trap - EXIT
echo 444
# sortie
# 111
# ./xxx.sh: ligne xx: commande inconnue : commande introuvable
# 333
|
Signaux
EXIT |
appel d'«exit» ou sortie du script suite avec l'option «set -e» suite à une erreur
|
INT |
Ctrl-C from the keyboard
|
TERM |
kill du processus
|
Fonctions
|
# Les signatures de fonction ne contiennent pas de paramètres
Fonction() {
$0 # nom du fichier de script avec son chemin tel qu'il a été appelé
$1 # argument 1
$@ # liste des tous les arguments
$# # nombre d'arguments ($0 compris)
local variable_locale="pouet!"
echo $FUNCNAME // nom de la fonction: Fonction
return 0 # code de retour
}
# La méthode doit être déclarée avant d'être utilisée
Methode arg1 arg2
# code de retour de la méthode (return)
echo $?
# stocke dans var toutes les valeurs émises par echo depuis Methode
var=$(Methode arg1 arg2)
|
|
Par défaut dans bash les variables sont globales.
Les variables sont donc accessibles dans et à l'extérieur des fonctions. |
Lire et écrire dans un fichier
|
# écrire 1 dans « fichier.txt ». Le contenu du fichier est écrasé. Le fichier est créé s'il n'existait pas.
echo 1 > fichier.txt
# écrire 1 à la suite du contenu existant dans « fichier.txt ». Le fichier est créé s'il n'existait pas.
echo 1 >> fichier.txt
# lire le contenu de « fichier.txt » et le stocker dans « ma_variable »
ma_variable=$(cat fichier.txt)
|
extglob option
Permet d'étendre les pattern matching operators:
Operators
|
Explanations
|
?(pattern-list) |
Matches zero or one occurrence of the given patterns
|
*(pattern-list) |
Matches zero or more occurrences of the given patterns
|
+(pattern-list) |
Matches one or more occurrences of the given patterns
|
@(pattern-list) |
Matches one of the given patterns
|
!(pattern-list) |
Matches anything except one of the given patterns
|
|
# affiche si l'extglob option est activée ou non
shopt extglob
# active l'extglob option
shopt -s extglob
# désactive l'extglob option
shopt -u extglob
# liste tous les fichiers qui ne se terminent pas par -small.jpg
ls !(*-small.jpg)
|
|
# exécution dans le même processus
# possibilité d'utiliser les variables et les fonctions
. /chemin/vers/un/autre/script.sh
source /chemin/vers/un/autre/script.sh
. "$(dirname $0)/un_autre_script.sh"
# exécution dans un nouveau processus
/chemin/vers/un/autre/script.sh
bash /chemin/vers/un/autre/script.sh
|
Hasher un string
|
echo -n "mon string" | md5sum
echo -n "mon string" | sha512sum
|
Free Password Hash Cracker
Astuces
Quitter le script
|
exit 0
|
|
0 : succès
1 ou plus : erreur |
Enchaînement de commandes et test code de retour
Si la commande a fonctionnée elle renvoie 0 et le code après les && est éxecuté,
dans le cas contraire la commande n'a pas fonctionné correctement et a renvoyé 1, le code après les || est alors exécuté.
|
commande && echo ok || echo ko
commande
if [ $? -ne 0 ]; then
echo ko
fi
|
Chemin absolu du script et de son dossier
|
$(realpath "$0")
$(dirname "$(realpath "$0")")
|
True / False
|
true; echo $? # 0. A successful command returns 0.
false; echo $? # 1. An unsuccessful command returns 1.
echo $((1 == 1)) # 1. An arithmetic expression returns 1 for true.
ok=true
if [[ ${ok} == true ]]
# avec des entiers : 0=false, tous les autres = true
ok=0
if ((ok)) # faux
ok=1
if ((ok)) # vrai
|
Max
|
max() {
if (( $# != 2 )); then
return 1
fi
if (( $1 == $2 )); then
echo $1
else
if (( $1 > $2 )); then
echo $1
else
echo $2
fi
fi
return 0
}
# utilisation
m=$(max 10 5) # m=10 $?=0
m=$(max 10) # m= $?=1
|
Forcer la sortie en anglais
|
LC_ALL=C macommande
|
Relancer le script avec un autre utilisateur
|
# script lancé avec root
# test si c'est bien l'utilisateur 1000 qui à la main
# sinon on relance avec l'utilisateur 1000
if [[ $UID -ne 1000 ]]; then
su user1000 -c "bash $0"
exit $?
fi
|
Relancer le script avec script pour créer un fichier de log
|
# on test si la variable restart est définie
if [ -z ${restart+x} ]; then
export restart=true
script_path=$(realpath "$0")
dir_path=$(dirname ${script_path})
file_name=$(basename "$0")
# on relance le script avec script pour créer un fichier de log
script -q -c "${script_path}" "${dir_path}/${file_name%.*}.log" && exit
fi
# commandes du script ...
|
Test si l'utilisateur est root
|
if [[ $UID -ne 0 ]]; then
echo 'Only the root user can run this script.'
exit 1
fi
|
Lancer une commande avec root sans demande de mot de passe
|
# un utilisateur autre que root lance la commande suivante en tant que root
echo 'mot de passe' | su -c 'ma commande'
|
Mise en forme la sortie en colonnes
|
# mise en colonnes en fonction de la taille du terminal
ls -1 | column
# beaucoup d'espace entre les colonnes et beaucoup d'espace tout à droite
# mise en forme en 3 colonnes
# ne dépend pas de la taille du terminal
ls -1 | pr -3 -t
# beaucoup d'espace entre les colonnes (tabs)
# tronque le contenu des colonnes au besoin s'il dépasse
# mise en forme en 3 colonnes
# ne dépend pas de la taille du terminal
# 2 espaces entre chaque colonne
ls -1 | pr -3 -t -s'|' | column -t -s'|'
|
Alias console
~/.bashrc
|
alias ll='ls -alF'
# Utilisation des simple quotes dans l'alias
alias ds='df -t ext4 -h | grep home | awk '"'"'{ print $4 }'"'"''
# suppression d'un alias
unalias ll
|
Les alias peuvent être écrit dans un fichier séparé : .bash_aliases
~/.bashrc
|
# test si le fichier existe
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
|
Fonctions console
~/.bashrc
|
# Utilisation des paramètres via les fonctions
function fn() { sudo find / -name ''$1'' ;}
# awk et les argument de la fonction
function fit()
{
find . -type f -exec awk -v vawk="$1" '$0 ~ vawk {c++} c>0 {print ARGV[1] ; exit 0 } END { if (! c) {exit 1}}' \{\} \;
}
# les arguments de fonctions sont $1 ... $9
function xxx()
{
echo $1
}
xxx *.pdf
# *.pdf va être transformé en file1.pdf file2.pdf
# pour éviter cela
xxx "*.pdf"
xxx \*.pdf
|
~/.bashrc
|
PS1="\[\e[1;34m\]\w\$(if [[ \$(expr length \"\w\") -gt 50 ]]; then echo \"\n\r\"; else echo \" \"; fi)➭ \[\e[0m\] "
|
Codes
- \u : login de l'utilisateur
- \h : le nom de la machine
- \w : le répertoire courant
- \$ : # pour root, sinon $
Couleurs
|
# Reset
Color_Off='\e[0m' # Text Reset
# Regular Colors
Black='\e[0;30m' # Black
Red='\e[0;31m' # Red
Green='\e[0;32m' # Green
Yellow='\e[0;33m' # Yellow
Blue='\e[0;34m' # Blue
Purple='\e[0;35m' # Purple
Cyan='\e[0;36m' # Cyan
White='\e[0;37m' # White
# Bold
BBlack='\e[1;30m' # Black
BRed='\e[1;31m' # Red
BGreen='\e[1;32m' # Green
BYellow='\e[1;33m' # Yellow
BBlue='\e[1;34m' # Blue
BPurple='\e[1;35m' # Purple
BCyan='\e[1;36m' # Cyan
BWhite='\e[1;37m' # White
# Underline
UBlack='\e[4;30m' # Black
URed='\e[4;31m' # Red
UGreen='\e[4;32m' # Green
UYellow='\e[4;33m' # Yellow
UBlue='\e[4;34m' # Blue
UPurple='\e[4;35m' # Purple
UCyan='\e[4;36m' # Cyan
UWhite='\e[4;37m' # White
# Background
On_Black='\e[40m' # Black
On_Red='\e[41m' # Red
On_Green='\e[42m' # Green
On_Yellow='\e[43m' # Yellow
On_Blue='\e[44m' # Blue
On_Purple='\e[45m' # Purple
On_Cyan='\e[46m' # Cyan
On_White='\e[47m' # White
# High Intensity
IBlack='\e[0;90m' # Black
IRed='\e[0;91m' # Red
IGreen='\e[0;92m' # Green
IYellow='\e[0;93m' # Yellow
IBlue='\e[0;94m' # Blue
IPurple='\e[0;95m' # Purple
ICyan='\e[0;96m' # Cyan
IWhite='\e[0;97m' # White
# Bold High Intensity
BIBlack='\e[1;90m' # Black
BIRed='\e[1;91m' # Red
BIGreen='\e[1;92m' # Green
BIYellow='\e[1;93m' # Yellow
BIBlue='\e[1;94m' # Blue
BIPurple='\e[1;95m' # Purple
BICyan='\e[1;96m' # Cyan
BIWhite='\e[1;97m' # White
# High Intensity backgrounds
On_IBlack='\e[0;100m' # Black
On_IRed='\e[0;101m' # Red
On_IGreen='\e[0;102m' # Green
On_IYellow='\e[0;103m' # Yellow
On_IBlue='\e[0;104m' # Blue
On_IPurple='\e[0;105m' # Purple
On_ICyan='\e[0;106m' # Cyan
On_IWhite='\e[0;107m' # White
|
Exemples
Lister les dossiers par ordre décroissant de création
|
ls -t | while read element
do
[[ -d $element ]] || continue
echo $element
done
# for element in $(ls -t) ne permet pas gérer les noms avec espaces
# ls -rt pour trier par ordre croissant de création
|
Récupérer le nom du fichier / dossier le plus récent
|
set +u
unset -v latest
for element in *; do
[[ $element -nt $latest ]] && latest=$element
done
set -u
echo $latest
|
Renommer tous les fichiers ayant pour extension "TXT" en "txt"
Par exemple "file.TXT" devient "file1.txt" :
|
SUFF=TXT
suff=txt
for i in *.$SUFF
do
mv -f $i ${i%.$SUFF}.$suff
done
|
|
Si aucun fichier *.TXT n'existe, le script a un comportement bizarre. |
Suppression des dossiers .svn
dans le répertoire courant et dans tous les sous-répertoires :
|
DelDotSvnDirectory()
{
# liste de tous les sous répertoires.
for subDirectory in $(ls -l | grep ^d |
awk '{ for (i=9; i<NF; i++) printf $i"°" ; print $NF }')
do
# Lancement récursif de la méthode dans tous les sous-répertoires.
cd "${subDirectory//°/ }"
DelDotSvnDirectory
done
# Suppression du dossier .svn
if [ -d ".svn" ]; then
rm -rf ./.svn
fi
cd ..
}
DelDotSvnDirectory
|