Aide-mémoire Bash / Shell Linux
Structure et Entêtes
ObjectifCommande
Entête recommandée #!/usr/bin/env bash
set -euo pipefail
# -e : arrêt sur erreur
# -u : erreur si variable non définie
# -o pipefail : propager erreurs dans les pipes

readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_NAME="$(basename "$0")"
Exécuter un script chmod +x script.sh
./script.sh
bash script.sh
bash -x script.sh  :: mode debug (affiche les commandes)
bash -n script.sh  :: vérifier la syntaxe sans exécuter
Commentaires # Commentaire sur une ligne

: ' Commentaire multiligne '
Variables
Déclaration et utilisation nom="Jean"                     :: pas d'espace autour de =
echo "Bonjour $nom"
echo "Bonjour ${nom}"           :: délimiteur explicite
readonly PI=3.14159             :: constante
export VAR="valeur"            :: exporter vers les sous-shells
Variables spéciales $0    :: nom du script
$1 $2 ... :: arguments positionnels
$#    :: nombre d'arguments
$@    :: tous les arguments (liste)
$*    :: tous les arguments (chaîne)
$?    :: code retour de la dernière commande
$$    :: PID du script en cours
$!    :: PID de la dernière commande en arrière-plan
$_    :: dernier argument de la commande précédente
Valeurs par défaut ${var:-"defaut"}  :: valeur si var vide ou non définie
${var:="defaut"}  :: assigner si vide ou non définie
${var:?"message"} :: erreur si vide ou non définie
${var:+"autre"}   :: "autre" si var définie et non vide
Arithmétique ((n = 5 + 3))
((n++))
((n += 10))
result=$((10 * 3 + 1))
echo $((2 ** 10))  :: puissance : 1024

:: Virgule flottante (bc)
result=$(echo "scale=2; 10/3" | bc)
result=$(echo "sqrt(144)" | bc -l)
Manipulation de Chaînes
Longueur et sous-chaîne s="Bonjour Monde"
${#s}               :: longueur : 13
${s:0:7}           :: Bonjour (pos 0, 7 chars)
${s:8}             :: Monde (à partir de 8)
${s: -5}           :: Monde (5 derniers)
Remplacements ${s/Monde/World}    :: remplacer première occurrence
${s//o/0}           :: remplacer toutes
${s/#Bonj/Allo}     :: si commence par Bonj
${s/%onde/ito}      :: si finit par onde
Suppression de préfixe/suffixe fichier="archive.tar.gz"
${fichier#*.}     :: tar.gz (préfixe court *. )
${fichier##*.}    :: gz (préfixe long *. )
${fichier%.*}     :: archive.tar (suffixe court)
${fichier%%.*}    :: archive (suffixe long)
Casse ${s,,} :: tout en minuscule (bash 4+)
${s^^} :: tout en majuscule
${s,}  :: première lettre en minuscule
${s^}  :: première lettre en majuscule
Tests sur chaînes [[ -z "$s" ]]  :: vrai si chaîne vide
[[ -n "$s" ]]  :: vrai si non vide
[[ "$s" == "val" ]]
[[ "$s" != "val" ]]
[[ "$s" == *"sous"* ]]  :: contient "sous"
[[ "$s" =~ ^[0-9]+$ ]] :: regex
Conditions (if / test)
if / elif / else if [[ $age -ge 18 ]]; then
  echo "Majeur"
elif [[ $age -ge 16 ]]; then
  echo "Presque"
else
  echo "Mineur"
fi
Tests numériques [[ $n -eq 5 ]]  :: égal
[[ $n -ne 5 ]]  :: différent
[[ $n -gt 5 ]]  :: plus grand
[[ $n -ge 5 ]]  :: plus grand ou égal
[[ $n -lt 5 ]]  :: plus petit
[[ $n -le 5 ]]  :: plus petit ou égal
Tests sur fichiers [[ -e fichier ]]  :: existe
[[ -f fichier ]]  :: est un fichier régulier
[[ -d chemin ]]   :: est un dossier
[[ -L fichier ]]  :: est un lien symbolique
[[ -r fichier ]]  :: lisible
[[ -w fichier ]]  :: écritable
[[ -x fichier ]]  :: exécutable
[[ -s fichier ]]  :: non vide (taille > 0)
[[ f1 -nt f2 ]]   :: f1 plus récent que f2
Opérateurs logiques [[ cond1 && cond2 ]]  :: ET
[[ cond1 || cond2 ]]  :: OU
[[ ! cond ]]          :: NON

cmd1 && cmd2  :: exécuter cmd2 si cmd1 réussit
cmd1 || cmd2  :: exécuter cmd2 si cmd1 échoue
case case "$var" in
  "oui"|"yes")
    echo "affirmé";;
  non|no)
    echo "négatif";;
  [0-9]*)
    echo "commence par un chiffre";;
  *)
    echo "autre";;
esac
Boucles
for (liste) for item in a b c; do
  echo "$item"
done

for f in *.txt; do
  echo "Fichier : $f"
done
for (numérique) for ((i=1; i<=10; i++)); do
  echo $i
done

for i in {1..10}; do echo $i; done
for i in {0..100..10}; do echo $i; done :: pas de 10
while / until while [[ $i -lt 10 ]]; do
  ((i++))
done

while IFS= read -r ligne; do
  echo "$ligne"
done < fichier.txt

until [[ $i -ge 10 ]]; do
  ((i++))
done
Contrôle break    :: sortir de la boucle
continue :: passer à l'itération suivante
break 2  :: sortir de 2 niveaux de boucles
Fonctions
Déclarer et appeler ma_fonction() {
  local arg1="$1"
  local arg2="$2"
  echo "arg1=$arg1, arg2=$arg2"
}
ma_fonction "valeur1" "valeur2"
Valeur de retour est_majeur() {
  [[ $1 -ge 18 ]]  :: return 0 (succès) ou 1 (échec)
}

if est_majeur 20; then echo "Majeur"; fi

:: Retourner une chaîne via stdout
get_date() { date +%Y-%m-%d; }
d=$(get_date)
Variables locales fonction() {
  local var_locale="visible uniquement ici"
  global_var="visible partout"
}
Tableaux
Tableaux indexés t=("a" "b" "c")
t[3]="d"
echo "${t[0]}"          :: a
echo "${t[@]}"          :: tous les éléments
echo "${#t[@]}"         :: nombre d'éléments
t+=("e")               :: ajouter
unset t[2]             :: supprimer élément

for item in "${t[@]}"; do echo "$item"; done
Tableaux associatifs (bash 4+) declare -A config
config[host]="localhost"
config[port]=3306
echo "${config[host]}"
for key in "${!config[@]}"; do
  echo "$key = ${config[$key]}"
done
Entrée / Sortie et Redirection
Redirection cmd > fichier      :: stdout vers fichier (écrase)
cmd >> fichier     :: stdout vers fichier (ajouter)
cmd 2> erreurs    :: stderr vers fichier
cmd 2>&1          :: stderr vers stdout
cmd >> log 2>&1   :: tout vers log
cmd > /dev/null   :: supprimer stdout
cmd &> /dev/null  :: supprimer tout
Here-doc et here-string cat <<EOF
Ligne 1 avec $variable
Ligne 2
EOF

cat <<'EOF'  :: pas d'interpolation
$dollar non interprété
EOF

grep "pattern" <<<"chaine" :: here-string
Lire l'entrée read -r nom                :: lire une ligne
read -r -p "Votre nom : " nom :: avec prompt
read -r -s -p "Mot de passe : " mdp :: silencieux
read -r -t 10 nom           :: timeout 10s
read -r -a tableau <<<"a b c" :: lire dans un tableau
Substitution de commande date_str=$(date +%Y-%m-%d)
nb_fichiers=$(ls * | wc -l)
contenu=$(cat fichier.txt)
Process substitution diff <(sort fichier1.txt) <(sort fichier2.txt)
while read line; do ...; done <(grep "err" log.txt)
Fichiers et Dossiers
Opérations courantes cp src dst             :: copier
cp -r src/ dst/       :: copier dossier
mv src dst             :: déplacer/renommer
rm fichier             :: supprimer
rm -rf dossier/       :: supprimer récursif
mkdir -p a/b/c         :: créer arborescence
find . -name "*.log"  :: chercher
find . -name "*.log" -mtime +7 -delete :: supprimer logs > 7j
find . -type f -size +10M :: fichiers > 10 Mo
Traitement de texte grep "pattern" fichier.txt
grep -r "pattern" dossier/
grep -i "Pattern"     :: insensible à la casse
grep -v "pattern"     :: inverser
grep -E "regex+"      :: regex étendue
grep -c "pattern"     :: compter les lignes

sed 's/ancien/nouveau/g' fichier
sed -i 's/ancien/nouveau/g' fichier :: en place
sed -n '5,10p' fichier             :: lignes 5 à 10

awk '{print $1,$3}' fichier  :: colonnes 1 et 3
awk -F',' '{print $2}' f.csv :: csv, col 2
awk '/pattern/{print}' f     :: lignes avec pattern
awk '{sum+=$1} END{print sum}' f :: somme col 1
Tri et déduplication sort fichier.txt
sort -r fichier.txt           :: inversé
sort -n fichier.txt           :: numérique
sort -k2 -t',' fichier.csv    :: par colonne 2
uniq fichier.txt              :: supprimer doublons contigus
sort fichier.txt | uniq       :: dédupliquer
sort fichier.txt | uniq -c    :: compter
Processus et Signaux
Gestion processus cmd &            :: lancer en arrière-plan
jobs             :: lister les jobs
fg %1           :: ramener au premier plan
bg %1           :: reprendre en arrière-plan
wait $!         :: attendre le dernier background
wait             :: attendre tous les backgrounds
nohup cmd &     :: résiste à la déconnexion
disown %1       :: détacher du shell
Signaux et trap trap 'echo "Interrompu"' INT  :: Ctrl+C
trap 'echo "Terminé"' EXIT   :: à la fin
trap 'nettoyage' ERR         :: sur erreur

:: Nettoyage automatique
trap 'rm -f "$tmp_file"' EXIT
tmp_file=$(mktemp)
Bonnes Pratiques et Astuces
Logging LOG_FILE="/var/log/monscript.log"

log() {
  echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}

log "INFO" "Démarrage"
log "ERROR" "Quelque chose a échoué"
Parsing des arguments while [[ $# -gt 0 ]]; do
  case $1 in
    -f|--fichier) FICHIER="$2"; shift 2;;
    -v|--verbose) VERBOSE=1; shift;;
    -h|--help) usage; exit 0;;
    *) echo "Option inconnue: $1"; exit 1;;
  esac
done

:: Avec getopts (POSIX)
while getopts "f:vh" opt; do
  case $opt in
    f) FICHIER="$OPTARG";;
    v) VERBOSE=1;;
    h) usage; exit 0;;
  esac
done
Verrouillage (éviter doublons) LOCKFILE="/tmp/$(basename $0).lock"

if ! mkdir "$LOCKFILE" 2>/dev/null; then
  echo "Script déjà en cours (${LOCKFILE})"
  exit 1
fi
trap 'rm -rf "$LOCKFILE"' EXIT
Couleurs dans le terminal RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'  :: No Color

echo -e "${GREEN}Succès${NC}"
echo -e "${RED}Erreur : $msg${NC}"
Vérifier les dépendances require_cmd() {
  command -v "$1" >/dev/null 2>&1 || {
    echo "Erreur : '$1' est requis mais non installé."
    exit 1
  }
}
require_cmd curl
require_cmd jq
require_cmd docker
Vérifier droits root if [[ $EUID -ne 0 ]]; then
  echo "Ce script doit être exécuté en root."
  exit 1
fi
shellcheck shellcheck script.sh                    :: analyser le script
shellcheck -S warning script.sh        :: seuil avertissement
:: Installer : apt install shellcheck / brew install shellcheck