Afficher la pageAnciennes révisionsLiens de retourHaut de page Cette page est en lecture seule. Vous pouvez afficher le texte source, mais ne pourrez pas le modifier. Contactez votre administrateur si vous pensez qu'il s'agit d'une erreur. ====== Bash ====== * [[linux:zsh|ZSH]] * [[https://connect.ed-diamond.com/Linux-Pratique/lp-124/optimiser-sa-configuration-de-bash|Optimiser sa configuration de Bash]] * [[https://github.com/dylanaraps/pure-bash-bible]] * [[http://aral.iut-rodez.fr/fr/sanchis/enseignement/IntroProgBash_2022-06-03.pdf|Introduction à la programmation en Bash]] * [[https://mywiki.wooledge.org/ParsingLs|Why you shouldn't parse the output of ls(1)]] * [[https://connect.ed-diamond.com/linux-pratique/lp-133/rendre-ses-scripts-bash-plus-fiables|Rendre ses scripts « Bash » plus fiables]] * [[https://nochlin.com/blog/6-techniques-i-use-to-create-a-great-user-experience-for-shell-scripts|6 Techniques I Use to Create a Great User Experience for Shell Scripts]] * [[https://blog.smarchal.com/bash-substitutions-variables|Les substitutions de variables en bash]] ==== Utiliser les arguments de la commande précédente ==== [[https://stackoverflow.com/questions/3371294/how-can-i-recall-the-argument-of-the-previous-bash-command/3371711|Source]] Utiliser ''Alt+.'' ==== Lire ligne par ligne ==== === Un fichier === <code bash> while read variable; do echo $variable done < fichier.txt for p in $(cat dico); do echo $p done </code> La boucle ''for'' lit mot par mot alors que la boucle ''while'' lit vraiment ligne par ligne. === Une commande === On peut utiliser la substitution de commande: <code bash> while read f do echo $f done < <(ls) </code> ==== Substitution de commande ==== //command substitution// ou //process substitution// * [[https://unix.stackexchange.com/questions/17107/process-substitution-and-pipe]] * [[https://askubuntu.com/questions/678915/whats-the-difference-between-and-in-bash]] La syntaxe ''<(commande)'' renvoie le chemin vers un fichier contenant la sortie de la commande ''commande'' (cela semble être un tube anonyme). On peut donc faire des choses comme ça: <code bash> cat <(date) # lit le contenu du fichier cat < <(date) # redirige le contenu du fichier vers l'entrée standard de cat </code> ==== Conditions ==== * [[https://fr.wikibooks.org/wiki/Programmation_Bash/Tests]] * [[https://openclassrooms.com/fr/courses/43538-reprenez-le-controle-a-laide-de-linux/43394-les-conditions]] * [[https://jmmv.dev/2020/03/test-bracket.html|test, [, and [[]] <code bash> if [ $1 -ge 20 ] then echo "Vous avez envoyé 20 ou plus" else echo "Vous avez envoyé moins de 20" fi if [ "$1" != "-n" ] then echo "Do something" fi </code> === Si une chaîne de caractère commence par un motif === [[https://stackoverflow.com/questions/2172352/in-bash-how-can-i-check-if-a-string-begins-with-some-value]] <code bash> [[ $a == z* ]] # True if $a starts with a "z" (wildcard matching). [[ $a == "|"* ]] # True is $a starts with a "|" (| is a reserved symbol, so quoting it is mandatory) [[ $a == "z*" ]] # True if $a is equal to z* (literal matching). </code> === Suivant le nombre de lignes retournées par une commande === <code bash> if [ `commande | wc -l` -eq 0 ] then commande fi </code> === Si une variable est définie === [[https://www.cyberciti.biz/faq/unix-linux-bash-script-check-if-variable-is-empty/|Source]] <code bash> if [ -z "$var" ] then echo "\$var is empty or not defined" else echo "\$var is NOT empty" fi </code> Pour tester à la fois la définition et le contenu: <code bash> if [ "${var}" == "1" ]; then echo "var = 1" fi </code> Pour une variable d'environnement: <code bash> if [[ -z "${DEPLOY_ENV}" ]]; then </code> === Si une variable contient un motif === <code bash> if [ `echo $var | grep -c "motif"` == "0" ]; then echo "Pas de motif" else echo "Trouvé !" fi </code> === Si un fichier existe === Ou n'existe pas : <code bash> if [ ! -e tasks.csv ] then rec2csv -d ";" tasks.rec > tasks.csv fi </code> === Négation === <code bash> if [ ! -e ".git" ] echo "Git folder doesn't exist" fi </code> === Comparer deux dates === [[https://unix.stackexchange.com/questions/84381/how-to-compare-two-dates-in-a-shell|source]] <code bash> todate=$(date -d 2013-07-18 +%s) cond=$(date -d 2014-08-19 +%s) if [ $todate -ge $cond ]; then break fi </code> ==== Renommer tous les fichiers d'un dossier ==== <code bash> for file in *; do mv $file `echo $file | cut -d . -f 5`-VOSTFR.avi; done </code> ==== Conserver les retours à la ligne en affichant une variable ==== Mettre la variables entre guillemets: <code bash> echo "$var" </code> ==== Rediriger les flux de sortie ==== [[https://askubuntu.com/questions/625224/how-to-redirect-stderr-to-a-file|Source]] * rediriger ''stderr'' vers ''stdout'': ''2>&1'' * tout rediriger vers un fichier: ''&> file'' === Rediriger un groupe de commandes ==== <code bash> { cmd1 cmd2 } > redirect.log </code> ==== Variables particulières ==== === Les variables des paramètres === [[https://openclassrooms.com/fr/courses/43538-reprenez-le-controle-a-laide-de-linux/43126-afficher-et-manipuler-des-variables#/id/r-43089|Source]] * ''$#'' contient le nombre de paramètres * ''$*'' contient tous les paramètres * ''$@'' contient tous les paramètres * ''$0'' est le nom du script * ''shift'' permet de décaler les paramètres. ''$*'' et ''$@'' sont identiques si ces variables ne sont pas utilisées entre guillemets: elles contiennent tous les arguments, lorsque plusieurs mots étaient entre guillemets pour former un unique paramètre, ces guillemets sont supprimés et tous les mots composants les paramètres sont considérés indépendants. ''"$*"'' contient tous les paramètres, mais considérés comme un unique paramètre; ''"$@"'' conserve les paramètres comme fournis en entrée ([[https://stackoverflow.com/questions/22589032/what-is-the-difference-between-and/22589151|source]]). <code bash> # Si on exécute ce script avec ./script.sh "Hello World" Foo Bar rm $* # rm: cannot remove ‘Hello’: No such file or directory # rm: cannot remove ‘World’: No such file or directory # rm: cannot remove ‘Foo’: No such file or directory # rm: cannot remove ‘Bar’: No such file or directory rm $@ # rm: cannot remove ‘Hello’: No such file or directory # rm: cannot remove ‘World’: No such file or directory # rm: cannot remove ‘Foo’: No such file or directory # rm: cannot remove ‘Bar’: No such file or directory rm "$*" # rm: cannot remove ‘Hello World Foo Bar’: No such file or directory rm "$@" # rm: cannot remove ‘Hello World’: No such file or directory # rm: cannot remove ‘Foo’: No such file or directory # rm: cannot remove ‘Bar’: No such file or directory </code> === Autres variables === * ''$?'' renvoie le code de retour de la dernière commande exécutée * ''$$'' est le PID du programme actuel ==== Savoir si le script est lancé en tant que root ==== [[https://www.cyberciti.biz/tips/shell-root-user-check-script.html|Source]] <code bash> if [ "$(id -u)" != "0" ]; then echo "This script must be run as root" 1>&2 exit 1 fi </code> ==== Connaître l'utilisateur derrière sudo ==== [[https://stackoverflow.com/questions/3522341/identify-user-in-a-bash-script-called-by-sudo|Source]] <code bash> user=${SUDO_USER:-$(whoami)} </code> ==== Booléens ==== [[https://stackoverflow.com/questions/2953646/how-can-i-declare-and-use-boolean-variables-in-a-shell-script]] <code bash> the_world_is_flat=true # ...do something interesting... if [ "$the_world_is_flat" = true ] ; then echo 'Be careful not to fall off!' fi </code> ==== Système d'options ==== [[http://linuxcommand.org/lc3_wss0120.php]] <code bash> set -u while [ $# -gt 0 ]; do case $1 in -f | --file ) shift filename=$1 ;; -i | --interactive ) interactive=1 ;; -h | --help ) usage exit ;; * ) usage exit 1 esac shift # inutile ? done </code> ==== Opérations arithmétiques ==== [[https://linuxize.com/post/bash-increment-decrement-variable/]] <code bash> i=$((i+1)) ((i=i+1)) let "i=i+1" ((i+=1)) let "i+=1" ((i++)) ((++i)) let "i++" let "++i" </code> ==== Connaître le chemin d'un script ==== [[https://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself|Source]] <code bash> SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" </code> ==== Boucles ==== Sur i: <code bash> for i in $(seq 0 5); do echo $i; done # de 0 à 5 compris for i in 0 25 50 75 100 125 150 175 200 225 250 275 300; do echo $i; done # équivalent à: for i in $(seq 0 25 300); do echo $i; done # Possibilité de factoriser: s=$(seq 1 10) for c in $c; do echo $c; done </code> <code bash> i=1 while [ $i -le 2048 ] do echo $i; i=$((i*2)) done </code> ==== Tableaux ==== * [[https://www.linuxjournal.com/content/bash-arrays]] <code bash> a=("foo" "bar") for item in ${a[*]} do echo $item done </code> === Ajouter un élément === [[https://linuxhint.com/bash_append_array/|Source]] <code bash> a=() a+=("foo") </code> === Inverser un tableau === [[https://unix.stackexchange.com/questions/412868/bash-reverse-an-array|Source]] <code bash> incremental_backups=$(echo "${incremental_backups_rev[@]} " | tac -s ' ') </code> ==== Chaînes de caractères ==== === Enlever le dernier caractère === [[https://unix.stackexchange.com/questions/144298/delete-the-last-character-of-a-string-using-string-manipulation-in-shell-script|Source]] <code bash> foo="abcde" echo "${foo::-1}" # abcd </code> === Enlever un préfixe === [[https://stackoverflow.com/questions/16623835/remove-a-fixed-prefix-suffix-from-a-string-in-bash|Source]] <code bash> v="/data/truc/foo" prefix="/data/truc/" echo ${v#"$prefix"} </code> ==== Chronométrer un programme ==== [[https://unix.stackexchange.com/questions/52313/how-to-get-execution-time-of-a-script-effectively|Source]] <code bash> # Précision à la seconde: start=`date +%s` stuff end=`date +%s` runtime=$((end-start)) # Précision sous la seconde: start=`date +%s.%N` stuff end=`date +%s.%N` runtime=$( echo "$end - $start" | bc -l ) </code> ==== Commentaires multi-lignes ==== [[https://stackoverflow.com/questions/43158140/way-to-create-multiline-comments-in-bash|Source]] <code bash> : ' This is a very neat comment in bash ' </code> ==== Générer un nombre aléatoire ==== * [[https://stackoverflow.com/questions/1194882/how-to-generate-random-number-in-bash]] <code bash> echo $((1 + $RANDOM % 10)) od -t u -N 4 /dev/urandom | head -n 1 | cut -f 2 -d ' ' </code> ==== Options Bash ==== === Récupérer le code de retour dans un pipe === Pour récupérer le code de retour de la première commande qui échoue dans un pipe ([[https://unix.stackexchange.com/questions/14270/get-exit-status-of-process-thats-piped-to-another|source]]) : <code bash> set -o pipefail gcc ... 2>&1 | tee out res=$? </code> === Ne pas développer * === Pour éviter que ''*'' soit remplacé par tous les fichiers et dossiers du dossier courant, lancer ''bash -f'' ([[https://stackoverflow.com/a/13484149|source]]). === Quitter à la moindre erreur === <code bash> set -e </code> === Changer des options pour une portion de script === Mettre la portion entre parenthèses ([[https://stackoverflow.com/questions/74525090/bash-set-x-only-for-the-duration-of-a-function|source]]) : <code bash> #!/bin/bash set -eu ( set -o pipefail set +e false | cat echo "after $?" ) echo "before second" false | cat echo "after $?" false echo "sould not print" </code> ==== Couleurs ==== Changer la couleur du texte affiché : * [[https://www.shellhacks.com/bash-colors/|Bash Colors]] Visualiser le rendu de toutes les couleurs ([[https://askubuntu.com/questions/27314/script-to-display-all-terminal-colors|source]]) : <code bash> for x in {0..8}; do for i in {30..37}; do for a in {40..47}; do echo -ne "\e[$x;$i;$a""m\\\e[$x;$i;$a""m\e[0;37;40m "; done; echo; done; done; echo "" msgcat --color=test </code> linux/bash.txt Dernière modification : 2025/10/26 14:47de phsw