2018-11-13
2019-07-25: add music list
2021-08-17: add sequense
2021-12-11: add getopts
2021-12-31: add linuxconfig.org opensource.com
Site avec des exemples de ligne de commande de dingue !!
http://www.commandlinefu.com/commands/browse
re-re-merci Thierry
Ressources: https://linuxconfig.org/bash-scripting-tutorial
Page très compète avec des exemples de script:
Merci @Thierry pour ces astuces:
echo {{1..3},7,{11..13}} 1 2 3 7 11 12 13 echo $(seq -w 1 10) 01 02 03 04 05 06 07 08 09 10
Création de 10 fichiers d'un coup:
$ touch files{1..10}.txt
$ find ~/Musique -type f > ~/dossier/musiques-liste
Permet la gestion des paramètres pour un script bash.
La doc: https://man7.org/linux/man-pages/man1/getopts.1p.html
Exemple de syntaxe:
$ echo $(date +'%Y-%m-%d_%H.%M.%S') 2018-10-24_13.35.04
→ Cherche dans tous les fichiers txt le mot “Agitateur” :
Affiche le(s) nom de fichier et les lignes avec leurs numéros de ligne (grep -n)
$ find . -iname "*.txt" -exec echo {} ';' -exec grep -n "Agitateur" {} ';' ./Ajout mnemonic.txt 6:%Q210.45 F1_agt_c1_km EBOOL "Fond 1 : Commande 103KM5 : Agitateur cuve de stockage C1" 7:%Q210.46 F1_agt_c2_km EBOOL "Fond 1 : Commande 103KM6 : Agitateur cuve de stockage C2" 8:%Q210.47 F1_agt_c3_km EBOOL "Fond 1 : Commande 103KM7 : Agitateur cuve de stockage C3" 9:%Q210.48 F1_agt_c4_km EBOOL "Fond 1 : Commande 104KM8 : Agitateur cuve de stockage C4" ./Modèle_ST.txt 2:(***** Agitateur cuve stockage 5 13M1 O45.0 *****)
for ((i=2017; i<=2070; i++)) do mkdir $i done
Ressources: merci Thierry
$ du -hs */ | sort -h 6,2M py35dj18/ 17M py27/ 58M py35dj110/ 144M py35dj110oups/ 161M py35/
$ tree -L 2 --du -h | less
re-merci Thierry
Fev 2018: MOOC Bash sur http://fun-mooc.fr
du mot (si le curseur est placé à la fin d’un mot, coupe le mot)
$ history [...] 1940 source /home/jc/dev/py/py35/bin/activate 1941 python manage.py runserver 1942 ll 1943 python manage.py makemigrations personal_calendar 1944 python manage.py runserver 1945 python manage.py migrate 1946 python manage.py runserver
Manipulation de l’historique
$ history -c # permet d’effacer l’historique $ history -w # nomDeFichier permet de sauver l’historique courant dans nomDeFichier $ history -r # nomDeFichier permet d’ajouter les commandes contenues dans nomDeFichier à l’historique courant.
Les commandes avec !
Ctrl + R
(reverse-i-search)'sour': source /home/jc/dev/py/py35/bin/activate
Réutiliser les arguments de la dernière commande
Modifier les arguments Syntaxe :
$ !!:s/clé1/clé2/
Exemple :
$ wc fichier1.txt 9 443 3024 fichier1.txt $ !!:s/1/2/ wc fichier2.txt 7 322 2155 fichier2.txt
$ i=1 $ mon_cv=Documents/cv $ echo $i $ cd $mon_cv
$ echo :qqchose: ::
$(commande) # exemple: $ echo ici:$(pwd) ici:/home/alice
$ rep=$(pwd) $ echo $rep /home/alice
$ names=$(cat lipsum.txt) $ echo $names Lorem ipsum dolor bla bla bla ...
$ cmd_ptr="ls -l /bin/z*" #compo. de la Cde dans la variable $ eval $cmd_ptr #exécution de la commande -rwxr-xr-x 1 root root 1937 oct. 27 2014 /bin/zcat -rwxr-xr-x 1 root root 1777 oct. 27 2014 /bin/zcmp -rwxr-xr-x 1 root root 5764 oct. 27 2014 /bin/zdiff -rwxr-xr-x 1 root root 140 oct. 27 2014 /bin/zegrep -rwxr-xr-x 1 root root 140 oct. 27 2014 /bin/zfgrep -rwxr-xr-x 1 root root 2131 oct. 27 2014 /bin/zforce -rwxr-xr-x 1 root root 5938 oct. 27 2014 /bin/zgrep -rwxr-xr-x 1 root root 2037 oct. 27 2014 /bin/zless -rwxr-xr-x 1 root root 1910 oct. 27 2014 /bin/zmore -rwxr-xr-x 1 root root 5047 oct. 27 2014 /bin/znew
Exemples:
# inhibition totale: $ echo '* $(pwd)' * $(pwd) # inhibition partielle: $ a=* $ echo "$a $(pwd)" * /home/alice $ echo ": : $a" # ici on teste avec des espaces : : * # inhibition caractère: anti-slash $ echo \$a $a $ echo - \ - - - $ echo - - - -
$ ls fichier1.txt # qui existe $ echo $? 0 $ ls fichier1.txt # qui n'existe PAS ls: fichier3.txt: No such file or directory $ echo $? 1
La commande ps -f
$ ps -f UID PID PPID C STIME TTY TIME CMD alice 85 1 0 1902 ttyS0 15049-12:58:15 -bash alice 156 85 0 1902 ttyS0 15049-12:58:15 ps -f $
$ sleep 1000 & [1] 950 $ kill -15 950 [1]+ Terminated sleep 1000
ou dans la liste de jobs :
$ jobs [1] Running macmd & [2] Running macmd & [3] Running macmd & [4]+ Stopped bash -r [5]- Running sleep 600 & $ kill %3 $ jobs [1] Running macmd & [2] Running macmd & [3] Terminated macmd [4]+ Stopped bash -r [5]- Running sleep 600 & $ jobs [1] Running macmd & [2] Running macmd & [4]+ Stopped bash -r [5]- Running sleep 600 & $
Arrêt groupé: Killall
$ jobs [1] Running macmd & [2]- Running macmd & [6]+ Running macmd & $ killall macmd $ [1] Terminated macmd [2]- Terminated macmd [6]+ Terminated macmd $ jobs $
Sortie standard: 2redirections
simple: > en ajout: >>
redirection vers un dispositif:
"trou noir" : >/dev/null
Sortie des erreurs
simple: 2> en ajout: 2>>
Entrées standard:
Redirection standard: <
Exemple avec wc (word count)
$ wc -l < fichier1.txt # en redirection 3 $ wc -l fichier1.txt # utilisation normale 3 fichier1.txt
Exemple: comtage du nombre de ligne donné par history:
$ history | wc -l 5547
$ printenv SDL_MOUSEDRV=TSLIB DISPLAY=:0 ps24=3 SDL_MOUSEDEV=/dev/input/event1 USER=alice PWD=/home/alice/Sequence2/A24 MANPAGER=less -R HOME=/home/alice TSLIB_TSDEVICE=/dev/input/event1 SHELL=/usr/bin/bash TERM=linux SHLVL=1 MANPATH=/usr/share/man LOGNAME=alice PATH=/bin:/usr/bin:.:/usr/script PS1=\[\e[32m\]\$\[\e[m\] HISTSIZE=10000 HISTFILESIZE=10000 _=/bin/printenv OLDPWD=/home/alice $
La commande set comme la commande shopt permet aussi de modifier les options du shell. La commande set -o permet de lister les options contrôlées par la commande set. Pour obtenir de l’aide sur cette commande : help -m set.
$ set [...] OPTERR=1 OPTIND=1 OSTYPE=linux-musl PATH=/bin:/usr/bin:.:/usr/script PIPESTATUS=([0]="0") PPID=1 PS1='\[\e[32m\]\$\[\e[m\] ' PS2='> ' PS4='+ ' PWD=/home/alice/Sequence2/A24 SDL_MOUSEDEV=/dev/input/event1 SDL_MOUSEDRV=TSLIB SHELL=/usr/bin/bash SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor SHLVL=1 TERM=linux TSLIB_TSDEVICE=/dev/input/event1 UID=1000 USER=alice _=set blue='\e[1;34m' mystere23='wc -c /home/alice/Sequence2/A25/lipsum.txt' p1=mystere p2=23 ps24=3 $
Ajouter la variable avec vi:
D=/home/alice/Documents/cv export D
Actualiser le bash:
$ source .bashrc
Permet de supprimer une variable
$ $ 1 $ $ var=1 echo $var unset var echo $var $
La commande declare sans paramètre affiche comme la commande set toutes les variables de la session courante. La seule différence est que la commande declare différencie les variables exportées.
Une variable créée par l’utilisateur dans un shell est dite locale. Elle n’est connue qu’a l’intérieur du shell qui l’a créée. Il peut arriver que l’on souhaite lancer un autre shell depuis le shell actuel. On appelle ce second shell un sous-shell. Les variables d’environnement du shell original sont “transmises” au sous-shell. Ainsi, si dans le shell d’origine la variable d’environnement HOME existe et est définie, dans le sous-shell cette variable existera aussi et aura la même valeur.
$ printenv [...] HOME=/home/mylogin [...] $ bash $ printenv [...] HOME=/home/mylogin [...]
Dans l’exemple ci-dessus, la deuxième commande bash lance le programme Bash dans le shell original. On vérifie que dans ce sous-shell, la variable d’environnement HOME est bien définie et a la même valeur que le shell original.
Exemple :
$ mytimezone=CET $ echo $mytimezone CET $ bash $ echo $mytimezone
Ci-dessus, la variable mytimezone n’est pas accessible au sous-shell.
$ mytimezone=CET $ echo $mytimezone CET $ export mytimezone $ printenv [...] mytimezone=CET [...] $ bash $ echo $mytimezone CET
Le fichier /etc/profile est un script exécuté automatiquement à la connexion pour tous les utilisateurs. Ce fichier définit les variables et paramètres universels identiques pour tous les utilisateurs. Attention, ce fichier est commun à plusieurs shells (sh, ksh, bsh, bash, · · · ). Il ne faut donc pas y mettre de variables spécifiques à Bash. Et si de telles variables spécifiques sont nécessaires il faut les mettre dans le fichier /etc/bashrc. L’exemple suivant montre un extrait de ce que peut contenir le fichier /etc/profile.
[...] PATH="$PATH:/usr/local/bin:/usr/bin" USER=‘id -un‘ LOGNAME=$USER export PATH USER LOGNAME [...]
Cet exemple montre que les variables d’environnement PATH, USER, LOGNAME sont définies et exportées en tant que variables d’environnement.
Le fichier ~/.profile ou /home/mylogin/.profile contrairement au fichier /etc/profile n’est exécuté que lorsque l’utilisateur mylogin se connecte. Ce fichier est exécuté après l’exécution du fichier /etc/profile - il permet donc de modifier les variables déjà définies dans /etc/profile ou d’en créer de nouvelles. Il est modifiable par l’utilisateur et contient les variables d’environnement qui lui sont spécifiques. C’est dans ce fichier par exemple que doit être créée puis exportée notre variable mytimezone. Pour ce faire, on doit ajouter les lignes suivantes dans ce fichier :
[...] mytimezone=CET export mytimezone [...]
Si le shell de l’utilisateur mylogin est Bash alors le script /home/mylogin/.bashrc est exécuté à la suite des fichiers /etc/profile et /home/mylogin/.profile. Le fichier /home/mylogin/.bashrc débute souvent par des commandes qui vont conduire à lancer l’exécution du fichier /etc/bashrc. Car ce dernier contient des variables, fonctions, ou alias propres à Bash et communs à tous les utilisateurs. La suite du fichier /home/mylogin/.bashrc et complétée par les définitions des variables, fonctions et alias spécifiques à l’utilisateur. Voici un extrait du contenu d’un fichier /home/mylogin/.bashrc
[...] if [ -f "/etc/bashrc" ] ; then source /etc/bashrc fi export EDITOR=/usr/bin/vi [...]
Les premières lignes testent si le fichier /etc/bashrc existe, et si c’est le cas l’exécutent avec la commande source. Puis, la variable EDITOR est définit et exporte. La valeur de cette variable est la commande de l’éditeur de texte par défaut de l’utilisateur.
Exemples de prompt :
$ PS1="\u > " alice > alice > PS1="\u dans \w > " alice dans ~ > cd /tmp alice dans /tmp >
Les commandes pouvant être utilisées pour personnaliser le prompt :
\u login de l’utilisateur courant \w répertoire courant, avec $HOME abrégé par un tilde \t Heure courante au format 24-heures HH:MM:SS \s Le nom du shell, aussi retourné par la variable $0 \T Heure courante au format in 12-heures HH:MM:SS \@ Heure courante au format in 12-heures AM/PM \A Heure courante au format in 24-heures HH:MM \H Nom de la machine \W Nom de base du répertoire courant, avec $HOME abrégé par un tilde \! Le numéro historique de la commande /# Le Numéro de la commande \n Passage à la ligne
Exemples head et tail:
$ head .bash_history [...] #10 première lignes du fichier par défaut $ tail .bash_history [...] #10 dernière lignes du fichier par défaut $ tail -5 .bash_history #5 première lignes
La commande split permet de découper un fichier en plusieurs morceaux.
L’exemple suivant permet de diviser le fichier /var/log/syslog en plusieurs fichiers de 22 octets, avec l’option -b 22, qui seront appelés : log_aa, log_ab, ….
$ split -b 22 /var/log/syslog log_
La commande suivante effectue la même division mais en séparant en fichiers ayant le même nombre de lignes, dans notre cas 30, avec l’option -l 30.
split -l 30 /var/log/syslog log_
$ wc -l .bash_history 5448 .bash_history
Exemples cut:
$ cut -f 1 -d " " .bash_history [...] ls cd vi
Les commande sort et uniq:
$ cut -f 1 -d " " .bash_history > /tmp/c $ sort /tmp/c > /tmp/d $ uniq -c /tmp/d [...] 1 whoami 3 whois 1 zsh
Connaître les 10 commandes les plus utilisées :
$ uniq -c /tmp/d | sort -nr | head 1161 ls 748 cd 333 cat 254 vim [...]
Trier dans ordre croissant des notes données aux actrices (colonne 3)
$ cat elle/notes/actress.csv | sort -t : -n -k 3 [...] Ryder:Winona:89 Berry:Halle:90 Swanson:Gloria:91 Wood:Ashley:91 Davis:Geena:99 Gillan:Karen:99 Weisz:Rachel:99
Extraire les noms et prénoms du CSV
$ cat elle/notes/actress.csv | cut -d ":" -f 1,2 [...] Kelly:Grace Swank:Hillary Goldberg:Whoopie Davis:Geena Zellweger:Renee Gillan:Karen $
Contrairement à la commande cut qui permet d’extraire des informations d’un fichier ou de l’entrée standard, la commande paste permet de fusionner les colonnes contenues dans plusieurs fichiers.
La commande paste permet de réunir les deux fichiers comme le montre l’exemple suivant. Attention, l’ordre dans lequel les fichiers sont donnés en paramètre est important.
$ paste low.txt high.txt 1 4 2 5 3 6
L’option -d permet de modifier le caractère de séparation qui par défaut est la tabulation.
$ paste -d : low.txt high.txt 1:4 2:5 3:6
La commande join est similaire à la commande paste car elle permet de mixer plusieurs informations provenant de fichiers ou de l’entrée standard. La commande join permet de joindre des fichiers en fonction de mots clés. Prenons l’exemple suivant :
$ cat nom.txt BROOKS Belle xx JACK Alice 10 DANIEL Beatrice 1 $ cat niveau.txt Alice bash guru Belle unknown status Beatrice bash newbie
Pour lier les deux fichiers en fonctions des prénoms, on utilise la commande suivante :
$ join -1 2 -2 1 nom.txt niveau.txt Alice JACK 10 bash guru Belle BROOKS xx unknown status Beatrice DANIEL 1 bash newbie
L’option -1 2 signifie que dans le premier fichier, soit dans notre cas nom.txt, le champ définissant la relation est la deuxième colonne. De même l’option -2 1 signifie que dans le second fichier, dans notre cas niveau.tItaliquext, le champ définissant la relation est la première colonne. Attention au fait que dans la sortie de la commande, chaque ligne commence par la clef de relation.
$ find . -iname "*.mkv" -size +1G -mtime -7 -o -iname "*.epub" -user alice -mtime -7 tralala tralala
$ find . -iname "*.mkv" -size +1G -mtime -7 -exec mv {} /tmp/. ';' -o -iname "*.epub" -user alice -mtime -7 -exec mv {} /tmp/. ';'
Quelques paramètres de find :
Exmples :
$ find /etc /bin -name "a*" $ find . -iname "d*" -type d # d pour les répertoires, l pour les liens symboliques et f pour les fichiers. #Liste toutes les entités du répertoire personnel qui ont été modifiées il y a moins de 7 jours. $ find $HOME -mtime -7 #Liste toutes les entités du répertoire courant dont la taille dépasse le méga octet $ find . -size +1M #Liste toutes les entités de votre répertoire personnel dont vous n’êtes pas le propriétaire, car l’option ! exprime la négation. $ find $HOME ! -user $LOGNAME
ET et OU avec la commande find
#Liste toutes les entités du répertoire courant dont la taille dépasse cinq méga octets mais dont la taille est aussi inférieure à un giga octet. $ find . -size +15M -size -1G #L’option -o de la commande find permet de chercher sur des unions de critères (OU). #Liste toutes les entités du répertoire courant dont le nom se termine par "*.py" ou par "*.cpp". $ find . -name "*.py" -o -name "*.cpp"
L’option -exec
$ find . -iname "*.jpg" -exec echo "AVANT" {} "APRES" ';'
Tous les {} sont remplacés par le chemin trouvé en protégeant automatiquement les espaces.
On peut enchaîner des actions avec plusieurs -exec et utiliser plusieurs fois {} dans la même commande :
$ find . -iname "*.txt" -exec wc -l {} ’;’ -exec cp {} {}.bak ’;’
→ Trouve toutes les entités dont le nom se termine par “*.txt”, puis exécute la commande wc -l sur les entités trouvées (représentée par {}) et ensuite copie les entités trouvées dans des fichiers de même nom avec l’extension {}.bak.
$ grep "^mpl.*mkv$" .bash_history tralala tralala
Les options de la commande les plus utilisées sont
# compter le nb de ligne qui ne contiennent pas UNIX: $ grep -vc UNIX slogan.txt 7
Les motifs de recherche utilisés par la commande grep sont les expressions régulières.
Exemple:
# début de ligne : $ grep ^Li slogan.txt Linux inside Live free or die UNIX # Fin de ligne $ grep ux$ slogan.txt Proudly powered by linux Kids are stronger with linux If you really want to know, look into linux # Commence par K ou U: $ grep ’^[KU]’ slogan.txt UNIX or nothing Kids are stronger with linux
Options courantes de la commande grep
Exemples gestion de lignes :
# 2 lignes avant, 3 lignes après: $ grep -B2 -A3 "nothing" slogan.txt # centré: 2 lignes avant/après $ grep -C2 "nothing" slogan.txt
$ grep "[A-Z].[v]" slogan.txt Give that man a Bash Live free or die UNIX
Exemple : On recherche les lignes contenant une lettre majuscule entre “R” et “Z”, puis 4 caractères minuscules entre “a” et “z” puis un espace. Ici le mot correspondant est “There”. Notez le caractère d’échappement \ avant l’accolade ouvrante et fermante.
$ grep ’[R-Z][a-z]\{4\} ’ slogan.txt There is nothing UNIX can’t buy
awk n’est pas à proprement parler une commande ou un filtre mais plutôt un langage de programmation. On le classe parmi les filtres programmables. awk est un outil de sélection et de manipulation de texte comme la commande grep. La syntaxe d’utilisation de la commande awk se présente sous la forme suivante :
$ awk ’commandes awk’ fichier
awk traite les lignes du fichier une à une et de manière séquentielle. Dans awk, chaque ligne contient un certain nombre de champs séparés par un séparateur qui par défaut est un espace. Ce séparateur peut être modifié avec l’option -F de awk, ou encore en changeant la valeur de la variable FS interne à awk. Cette variable est modifiable dans la partie ’commandes awk’ de la syntaxe ci-dessus.
Dans tout ce qui suit, les variables qui vont apparaître dans la partie ’commandes awk’ sont des variables internes à awk. C’est à dire que ce ne sont pas des variables accessibles depuis le shell, elles ont seulement un sens bien spécifique dans les traitements réalisés par awk. Pour awk une ligne complète est contenu dans la variable $0 et ses différents champs sont $1, $2, $3, … numérotés de
gauche à droite. Considérons le fichier wcs.txt suivant :
$ cat wcs.txt Ada LOVELACE 1815 1852 Annie EASLEY 1933 2011 Grace HOPPER 1906 1992
La commande suivante permet d’inverser l’ordre prénom-nom en nom-prénom dans le fichier wcs.txt :
$ awk ’{print $2 " " $1 " " $3 " " $4}’ wcs.txt LOVELACE Ada 1815 1852 EASLEY Annie 1933 2011 HOPPER Grace 1906 1992
Dans cette commande, les espaces entre les champs doivent être explicitement exprimés avec “ ”. Le mot clé print est un mot clé spécifique à awk qui permet d’afficher les variables. Comme spécifié précédemment, awk est un langage de programmation très riche, et nous n’entrerons pas dans les détails de celui-ci. Il permet de faire des calculs arithmétiques, de réaliser des tests logiques et contient
de nombreuses fonctions (dont les fonctions mathématiques courantes).
Par exemple, awk permet facilement d’effectuer des calculs sur les champs. L’exemple suivant montre le calcul de l’âge et l’ajout d’un texte au moment de l’affichage du résultat. L’exemple modifie aussi le séparateur entre l’année de naissance et l’année du décès.
$ awk ’{print $2 " " $1 " " $3 "-" $4 " age: " $4 - $3}’ wcs.txt LOVELACE Ada 1815-1852 age: 37 EASLEY Annie 1933-2011 age: 78 HOPPER Grace 1906-1992 age: 86
awk traite le ou les fichiers ligne par ligne, mais pas seulement. awk permet aussi de spécifier des blocs de pré-traitement et post-traitement. Ces blocs sont exécutés avant le traitement de la première ligne du ou des fichiers, et après le traitement de la dernière ligne. Pour cela, la syntaxe de awk à utiliser est la suivante (un bloc vide peut être omis) :
awk ’ BEGIN { traitements débuts, avant lecture fichier} { traitement courants, ligne par ligne} END {traitements fins, après parcours fichier} ’ fichier.
L’exemple suivant montre l’utilisation de ces blocs.
awk ’ BEGIN {print "Les informaticiennes :"} {print $2 " " $1 " " $3 "-" $4 " age: " $4 - $3} END {print "Il y en a : " NR ". On en veut plus."}’ wcs.txt Les informaticiennes : LOVELACE Ada 1815-1852 age: 37 EASLEY Annie 1933-2011 age: 78 HOPPER Grace 1906-1992 age: 86 Il y en a : 3. On en veut plus.
Le résultat de l’exemple précédent montre que l’on cherche à afficher, avant le traitement du fichier, la chaîne de caractères Les informaticiennes : présente dans le bloc BEGIN. Ensuite, à la fin du traitement nous avons cherché à afficher Il y en a : “ NR ”. On en veut plus.. La variable NR est une variable prédéfinie de awk qui contient le numéro de la ligne en cours d’analyse. Dans notre cas, puisque l’utilisation de cette variable se fait dans le bloc END, la valeur de NR correspond au numéro de la dernière ligne qui a été analysée. À l’affichage, cette variable est remplacée par sa valeur.
Exemple de base : La commande sed (stream editor) permet de modifier un flux de données de taille illimité en utilisant très peu de mémoire.
$ sed -i '' "/^mpl.*mkv$" .bash_history $ grep "^mpl.*mkv$" .bash_history rien !
La commande sed peut utiliser les expressions régulières qui en font un
filtre très puissant et dont les possibilités sont infinies. La commande sed lit les fichiers dont les noms
sont indiqués en paramètres. Si aucun nom n’est indiqué, elle lit l’entrée standard.
On lui indique les traitements à effectuer en utilisant l’option -e (la présence de cette option est facultative s’il n’y a qu’une seule directive de traitement). Par défaut les fichiers indiqués ne sont pas modifiés et le résultat de la transformation est écrit sur la sortie standard. Mais avec l’option -i on peut obtenir que le résultat soit écrit dans chacun des fichiers.
L’utilisation principale de la commande sed est la substitution d’une expression régulière par une chaîne de caractères, la forme syntaxique pour exprimer ce traitement est la suivante :
s/expression-reguliere/chaîne/g
L’option /g indique que toutes lignes validant l’expression régulière seront traitées, sinon le traitement s’arrêtera après la première occurrence trouvée. La commande sed permet d’utiliser les expressions régulières étendues avec l’option -r, nous n’entrerons pas dans ce type d’expressions régulières ici. Pour utiliser les caractères spéciaux tel que / ou & dans les expressions ou la chaîne, il faut utiliser le caractère d’échappement \. Il est possible d’effectuer plusieurs substitutions à la suite, elles seront alors traitées les unes après les autres et de gauche à droite.
Voici les exemples d’utilisation les plus courants :
$ sed ’s/alice/bob/g’ fichier1 fichier2
Lit le contenu des fichiers fichier1 et fichier2 et l’écrit sur la sortie standard en remplaçant tous les alice par bob.
Pour supprimer un mot il suffit de substituer le mot par une chaîne vide. Par exemple, pour supprimer le mot alice la commande est :
$ sed ’s/alice//g’ fichier1 fichier2
Il est possible d’utiliser la commande sed comme filtre :
$ cat fichier | sed -e ’s/a/A/g’ -e ’s/TA/ta/g’
La commande cat affiche le contenu du fichier fichier sur la sortie standard, qui est reprise par la commande sed (c’est le cas classique d’utilisation d’une commande filtre). Notez ici que nous avons utilisé l’option -e car la commande contient plusieurs directives de traitement. La première substitution change tous les a en A et la seconde tous les TA en ta. Ce qui signifie que si fichier contient une ligne a Table , cette ligne sera transformée en A table . En effet, la première substitution transformera :
a Table --> A TAble
et la deuxième substitution agira sur le résultat de la première substitution :
A TAble --> A table
Options classiques de sed
$ sed ’1,5s/UNIX/*nix/g’ slogan.txt
Ex: Permet de remplacer ’Bash’ par ’BASH’ sur les lignes commençant par ’C’.
$ sed -e ’/^C/s/Bash/BASH/g’ slogan.txt
La commande suivante permet de faire ce changement sur les lignes contenant le mot ’that’.
$ sed -e ’/that/s/Bash/BASH/g’ slogan.txt
La commande suivante remplacera toutes les chaînes de caractères commençant par ’L’ et se terminant par ’x’ avec n’importe quel nombre de caractère entre ces deux lettres par “XXX”.
$ sed -e ’s/L.*x/XXX/g’ slogan.txt
En remplaçant “XXX” par un “”, la chaîne de caractères sera supprimée (remplacée par une chaîne vide).
$ sed -i ’’ -e ’/^L*e$/d’ slogan.txt
L’option -i ” (avec les deux quotes) permet d’effectuer les modifications directement dans le fichier slogan.txt. Attention selon les versions de la commande sed l’option est -i ” (pour la famille Linux, GNU) ou -i (pour la famille Unix, BSD). Un autre exemple simple est la suppression de toute les lignes contenant le mot Linux.
$ sed -e ’/Linux/d’ slogan.txt
Options puissantes
Dans cet exemple le caractère & indique à la commande sed d’insérer la chaîne de caractère trouvée par l’expression régulière. Dans notre cas .* permet de sélectionner toute une ligne
$ sed -e ’s/.*/Je dis: &/’ slogan.txt
$ cat date.txt 2017-01-21 2019-11-09 2012-08-17 2003-15-13
→ Les régions (.*)-(.*)-(.*)
$ sed -e ’s/\(.*\)-\(.*\)-\(.*\)/date: \3 \2 \1/’ date.txt date: 21 01 2017 date: 09 11 2019 date: 17 08 2012 date: 13 15 2003
Exemple du Challenge A33:
Donner le nombre d'actrices différentes notées par tous les magazines :
$ find -name *.csv -exec cat {} ';' | cut -d ":" -f 1,2 | sort | uniq | wc -l
$ expr 1 + 2 3
$ a=$(expr 1 + 2) $ echo $a 3
# i est indéfinie. $ i=$(expr $i + 1) expr: syntax error $ i=$(expr "$i" + 1) $ echo $i 1
$ expr 10 + 6 / 2 13 $ expr \( 10 + 6 \) / 2 8
Opérateur | Libellé |
---|---|
\( expression \) | parenthésage |
\* | multiplication |
/ | division entière |
% | reste de la division entière |
+ | addition |
- | soustraction |
$ expr $a \* 3 6
$((expression))
$ a=2 $ a=$((a*3)) $ echo $a 6
$ $((i=1+2)) -bash: 3: command not found $ echo $i 3
Mais attention :
Opérateurs | Opérateurs |
---|---|
( ) | parenthésage |
++ – | incrément, décrément |
! | négation logique |
double étoile | puissance |
*/% | multiplication, division, reste |
+ - | addition, soustraction |
< = >= < > == != | comparaison |
&& | et logique |
double pipe | ou logique |
= *= /= %= -= += | affectation |
$ a=2 $ let "a=a+1" $ echo $a 3
$ ((a=a+1)) $ echo $a 4
Exemples d'utilisation :
$ ((a++)) $ echo $a 5
Variantes :
$ let "a=a+1" $ let "a+=1" $ ((a++))
Exemple d'erreur :
$ let a=a * 2 -bash: let: *: syntax error $ let "a=a * 2"
Compatibilité avec expr :
$ a=10 $ ((a = \( $a + 20 \) / 2 )) $ echo $a 15
Opérateurs | Opérateurs |
---|---|
( ) | parenthésage |
++ – | incrément, décrément |
! | négation logique |
double étoile | puissance |
*/% | multiplication, division, reste |
+ - | addition, soustraction |
< = >= < > == != | comparaison |
&& | et logique |
double pipe | ou logique |
= *= /= %= -= += | affectation |
$ declare -i b=10 $ b=(b+8)/2 $ echo $b 9
$ bc bc 1.06.95 Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc. This is free software with ABSOLUTELY NO WARRANTY. For details type `warranty'. scale=10 10/3 3.3333333333 quit $
$ echo "scale=10; 10/3" | bc 3.3333333333
$ c=$(echo "scale=10; 10/3" | bc) $ echo $c 3.3333333333
Les options les plus courantes de la commande tar sont :
$ tar cvf nom_a_creer.tar chemin_repertoire_existant
$ tar xvf nom_de_l_archive.tar
$ tar tvf nom_de_l_archive.tar
$ tar xvf nom_de_l_archive.tar rep
La commande gzip (GNU zip) permet de compresser des fichiers pour réduire la place qu’ils prennent sur le disque. Cette compression est souvent utilisée avant le transfert du fichier à travers un réseau de communication pour réduire le temps de transfert. La commande gzip s’utilise de la manière suivante :
$ gzip monFichier
Le résultat de cette commande est la création d’un fichier monFichier.gz et la suppression du fichier monFichier. Il est possible de donner plusieurs noms de fichiers ou de compresser récursivement un répertoire sans en charger la hiérarchie.
La commande gunzip (GNU unzip) permet de décompresser des fichiers d’extension .gz.
$ gunzip monFichier.gz
Va créer un fichier monFichier et détruire le fichier monFichier.gz.
Pour conserver le fichier original :
$ gunzip -c monFichier.gz > monFichier
La commande gzip est aussi une option de la commande tar. Ainsi dans la commande tar czvf f.tgz f/ l’option z permet de compresser directement l’archive créée. Dans notre cas, l’archive du répertoire f/ sera compressée et le résultat se trouvera dans le fichier f.tgz. L’extraction se passe de la même manière avec l’option x.
$1 -> arg1 $2 -> arg2 $3 -> arg3 $# -> 3 # nombre d'arguments $@ -> { arg1 arg2 arg3 } # liste des arguments
Pas de problème hors script :
$ TEXTE="Bonjour tous" $ echo $TEXTE Bonjour tous $
Avec un script :
$ TEXTE="Bonjour tous" $ ./ngArg.sh $TEXTE Il y a 2 argument(s) Le 1er est : Bonjour $
il faut utiliser l’inhibition partielle de la variable.
$ TEXTE="Bonjour tous" $ ./ngArg.sh "$TEXTE" #le script ngArg Il y a 1 argument(s) Le 1er est : Bonjour tous $
Pour indiquer un code de retour d'un script
exit 0 # ok exit 1 # erreur
${nom_variable:-valeur} # valeur par défaut pour un argument ${nom_variable:?message} # val var ou message err et stop script -> Contrôle argument obligatoire.
Exemples pas d'argument obligatoire: nbArg.sh
#!/bin/bash echo "Il y a $# argument(s)" FIRST=${1:-vide} echo "Le 1er est : $FIRST"
test :
$ ./nbArg.sh Il y a 0 argument(s) Le 1er est : vide
Exemples avec un argument obligatoire: arg1.sh
#!/bin/bash ARG1=${1:?"Vous devez fournir un argument"} echo "Le 1er est : $ARG1"
test :
$ ./arg1.sh ./arg1.sh line 3: 1: Vous devez fournir un argument $
La substitution de variable s’écrit dans sa forme complète avec des accolades : ${variable} La forme complète s’utilise quand le caractère qui suit le nom de la variable est un caractère alphanumérique ou le caractère souligné. Ainsi si dans notre script henri.sh nous devons faire un pseudonyme composé du nom et de l’âge, séparés par la lettre A, nous allons avoir besoin d’utiliser la forme complète. Voyons ce que cela donne :
#!/bin/bash AGE=45 NOM=Henri PSEUDO1="$NOMA$AGE" echo $PSEUDO1 # -> 45 PSEUDO2="${NOM}A$AGE" # -> HenriA45 echo $PSEUDO2
Dans un script on dit que les variables sont locales car les affectations de variables qu’on réalise ne vont pas se répercuter dans le contexte du processus qui a lancé l’exécution du script.
$ ./henri.sh 45 HenriA45 $ echo $PSEUDO1 $
Il existe un moyen de contourner ce comportement de localité des variables manipulées au sein d’un script. Il faut pour cela lancer l’exécution du script dans le même contexte d’exécution que le shell du terminal. Ceci se fait à l’aide de la commande source qui se note de manière abrégée par le symbole point (’.’) devant le nom du script à exécuter. On dit alors qu’on “source” le script.
$ source ./henri.sh 45 HenriA45 $ echo $PSEUDO1 45 $
On met en commentaire l'affectation de AGE.
#!/bin/bash #AGE=45 NOM=Henri [...]
On cré la variable AGE=30
$ AGE=30 $ ./henri.sh HenriA $
Cela est une nouvelle fois dû au fait que le shell du terminal et le script sont exécutés dans 2 processus différents et donc dans 2 contextes d’exécution différents. Il faut exporter la variable :
$ export AGE=30 $ ./henri.sh 30 HenriA30 $
Il est possible d’afficher chacune des commandes exécutées par un script à l’aide de l’option d’exécution -x du Bash :
$ bash -x script_a_lancer
Chaque commande exécutée sera alors affichée dans la console sur une ligne qui commencera par le caractère ’+’. On peut aussi demander l’affichage des lignes et des blocs lus avant leur traitement en ajoutant l’option –v :
$ bash -x -v script
Enfin, avant d’exécuter un script, il peut déjà être intéressant de savoir si la syntaxe du Bash a été respectée. Dans ce cas, l’option -n va vous permettre de lever les erreurs de syntaxe ou de vérifier l’absence d’erreur.
$ bash -n script
2 écritures:
Code retour:
Les opérateurs de comparaison arithmétique:
-eq | equal | égal à |
-ne | non equal | différent de |
-gt | greather than | strictement supérieur à |
-ge | greather or equal | supérieur ou égal à |
-lt | less than | strictement infértieur |
-le | less or equal | inférieur ou égal à |
Exemple :
$ [ 3 -gt 12 ]; echo $? 1
Opérateurs binaires :
Opérateurs unaires :
$ mot1=alice $ [ $mot1 = alice ]; echo $? 0 $ [ $mot1 \> bob ]; echo $? 1
# Vérifions que le fichier confidentiel n'est PAS accessible en lecture $ [ ! -r confidentiel ]; echo $? 0 $ [ ! -r confidentiel -a ! confidentiel ]; echo $? 1 $ [ ! -r confidentiel -a ! confidentiel -o ! -e confidentiel ]; echo $? 0
Ce que j'ai fais et qui fonctionne:
#!/bin/bash if [ $# -ne 0 ] then if [ -f $1 -a ! -w $1 ] then exit 0 else exit 1 fi else exit 1 fi
Ce qu'il fallait faire
### fichier exo2.sh ### #!/bin/bash [ -f "$1" -a ! -w "$1" ]
Cette commande apporte quelques facilités par rapport à la commande test :
$ [[ "bateau" < "navire" ]]; echo $? 0
$ [[ -e confidentiel && ! -r confidentiel ]]; echo $? 1
$ a=2 $ b=4 $ [[ $a*3 -gt 10 ]]; echo $? 1 $ [[ $a*3 -eq $b+2 ]]; echo $? 0
Dans un motif le caractère spécial * remplace n’importe quelle séquence de caractères (éventuellement aucun) ; le caractère spécial ? remplace n’importe quel caractère exactement une fois et les crochets permettent de remplacer exactement un des caractères indiqués entre les crochets.
$ [[ titu == t?t? ]]; echo $? 0 $ [[ taratata == t*a ]]; echo $? 0 $ [[ titu == t[aeiou]t[aeiou] ]]; echo $? 0
Ce que j'ai fait et qui fonctionne:
#!/bin/bash if [ $# -ne 0 ] then if [[ $1 == *X* && $1 == *Y* ]] then exit 0 else exit 1 fi else exit 1 fi
Ce qu'il fallais faire ! re
### fichier exo3.sh ### #!/bin/bash [[ "$1" == *X*Y* || "$1" == *Y*X* ]]
Nous avons vu dans l’activité 3.4 que la commande ( ( … ) ) permet de réaliser des calculs d’expressions arithmétiques et en particulier des tests arithmétiques. Cette commande n’affiche rien mais son code retour peut être utilisé pour réaliser des tests.
Dans le cas de tests arithmétiques si l’expression entre les doubles parenthèses est vraie le code retour vaut 0 et il vaut 1 sinon ce qui est équivalent aux résultats obtenus avec la commande test
$ a=2 $ b=4 $ [ $a -lt $b ]; echo $? 0 $ (( a < b )); echo $? 0 $ [ $a -eq $b ]; echo $? 1 $ (( a == b )); echo $? 1
Attention cependant si l’expression arithmétique n’est pas un test car l’interprétation du code retour est délicate. En effet le code retour obtenu est 0 si la valeur de l’expression entre les doubles parenthèses est différente de 0 et 1 si la valeur de l’expression vaut 0.
Ainsi le résultat d’une expression arithmétique dont on utilise le code retour comme un test est équivalent à faux si la valeur de l’expression est 0 et vrai sinon. Il est donc important de ne pas confondre le code retour et la valeur de l’expression entre parenthèse.
$ a=4 $ (( a-4 )); echo $? 1 $ (( a-2 )); echo $? 0 $ (( a / 10 )); echo $? 1 $ (( a / 2 )); echo $? 0
La valeur de l’expression arithmétique a − 4 est 0 donc le code retour de ( ( a-4 ) ) est 1, ce qui, utilisé comme un test, est équivalent à faux. L’interprétation serait donc « a est-il différent de 4 ? ». De la même manière l’interprétation du code retour de ( ( a-2 ) ) serait « a est-il différent de 2 ? » ; et pour ( ( a/10 ) ) : « la division entière de a par 10 est-elle différente de 0 ? » ou autrement dit « a est-il supérieur ou égal à 10 ? ».
Ce que j'ai fait et qui fonctionne:
#!/bin/bash if [ $# -eq 3 ] then # args list control: if [[ $1 < $2 && $2 < $3 ]] #if [[ $1 < $2 ]] then exit 0 else exit 1 fi else exit 1 fi
Ce qu'il fallait faire lol
### fichier exo1.sh ### #!/bin/bash [ $# -eq 3 -a "$1" \‹ "$2" -a "$2" \‹"$3" ]
enchaînement | code retour de cmd1 | code retour de cmd1 |
---|---|---|
cmd1 ; cmd2 | quelconque | toujours |
cmd1 && cmd2 | 0 ok !=0 nok | oui non |
cmd1 dbl pipe cmd2 | 0 ok !=0 nok | non oui |
# SI le fichier existe, on l'affiche: $ [ -f monCV ] && cat monCV $ echo $? 1 # le fichier n'existe pas
# SI le fichier existe, on l'affiche SINON on affiche un message $ [ -f monCV ] && cat monCV || echo "le fichier n'existe pas" le fichier n'existe pas
#!/bin/bash [ $# -eq 0 ] && echo "Vous n'avez pas donne votre reponse" && exit 3; [ $# -gt 1 ] && echo "Donnez une seule reponse" && exit 4; [ $# -eq 1 ] && [ $1 = "o" -o $1 = "O" ] && echo "oui" && exit 0; [ $# -eq 1 ] && [ $1 = "n" -o $1 = "N" ] && echo "non" && exit 1; echo "Pas compris" && exit 5
Correction:
### ouinon.sh ### #!/bin/bash [ $# -eq 0 ] && echo "Vous n'avez pas donné votre réponse" && exit 3 [ $# -gt 1 ] && echo "Donnez une seule réponse" && exit 4 [ "$1" = o ] || [ "$1" = O ] && echo oui && exit 0 [ "$1" = n ] || [ "$1" = N ] && echo non && exit 1 echo "Pas compris" && exit 5
#!§bin/bash if [ -f message -a -w message ] then echo "I love Bash !" >> message elif [ ! -e message ] then echo "I love Bash !" > message elif [ -f message -a ! -w message] then chmod u+w message echo "I love Bash !" >> message fi
#!/bin/bash if [[ $# > 1 && $# < 4 ]] then # 1er arg if [ -r $1 -a -r $1 -a -w $1 ] then # 2ème arg if [ -d $2 -a -x $2 ] then # 3ème arg if [ $# -eq 3 ] then if [ $3 -gt 0 ] then echo $3 exit 0 else echo "usage : testargu.sh fichier repertoire [nombre_positif ]" exit 6 fi # que 2 args else echo 999 exit 0 fi else echo "usage : testargu.sh fichier repertoire [nombre_positif ]" exit 5 fi else echo "usage : testargu.sh fichier repertoire [nombre_positif ]" exit 4 fi else echo "usage : testargu.sh fichier repertoire [nombre_positif ]" exit 3 fi
Correction :
### testargu.sh ### #!/bin/bash usage="usage : $0 fichier répertoire [nombre_positif]" # vérification du nombre d'arguments if [ $# -ne 2 -a $# -ne 3 ] then echo $usage ›&2 exit 3 fi # on teste le premier argument if [ ! -f $1 ] || [ ! -r $1 ] || [ ! -w $1 ] then echo $usage ›&2; exit 4 fi # on teste le deuxième argument if [ ! -d $2 ] || [ ! -x $2 ] then echo $usage ›&2; exit 5 fi # s'il y en a un, on teste le 3e argument if [ $# -eq 3 ] then if [ $3 -gt 0 ] then echo $3; exit 0 else echo $usage ›&2; exit 6 fi fi # Arriver ici il y a exactement 2 arguments echo 999
La syntaxe de l’instruction case est la suivante :
case expression in motif1) lignes-commandes1;; motif2) lignes-commandes2;; ... motifN) lignes-commandesN;; esac
Le script suivant écrit le type d’un fichier donné en argument en se fondant sur l’extension du nom de fichier. On utilise le caractère spécial * dans les filtres pour ignorer le nom du fichier jusqu’à l’extension. Le troisième cas est constitué de trois filtres séparés par une barre verticale.
#!/bin/bash # on teste d’abord qu’il y a bien exactement un argument # si ça n’est pas le cas on écrit un message d’erreur # qui rappel l’usage du script if [ $# -ne 1 ] then echo "Erreur : nombre d’argument incorrect" > &2 echo "Usage : $0 fich" > &2 else case $1 in *.c) echo "Code source en langage c";; *.sh) echo "Script bash";; *.jpeg | *.jpg | *.png) echo "Image";; *) echo "Type de fichier non reconnu";; esac fi
Ce deuxième exemple demande de répondre par oui ou non à une question donnée en argument (à condition qu’il y en ait une). Il prévoit toutes les formes de réponses possibles pour oui ou non.
#!/bin/bash if [ $# -eq 1 ] then echo "$1 ?" echo "Etes vous d’accord (oui ou non) ?" read rep case $rep in [oO] | [oO][uU][iI]) echo "Ok, merci";; [nN] | [nN][oO][nN]) echo "Tres bien, je respecte votre choix";; *) echo "Desole, je ne comprends pas votre reponse";; esac fi
repeat.sh
#!/bin/bash MOT=${1:?"Vous devez indiquer un mot"} NB=${2:-10} i=0 while [ $i - lt $NB ] ; do echo "$MOT" i=$(( $i + 1 )) done
$chmod +x repeat.sh $ ./repeat.sh Bonjour 3 Bonjour Bonjour Bonjour
testFor.sh
#!/bin/bash for CUR in Pierre Paul Jacques ; do echo $CUR done
$ chmod +x testFor.sh $ ./testFor.sh Pierre Paul Jaques $
afficheArg.sh
#!/bin/bash NUM=1 for V in $@ ; do echo "argument $NUM = $V" NUM=$(( $NUM + 1 )) done
$ chmod +x afficheArg.sh $ ./afficheArg.sh $ ./afficheArg.sh yop yep yap argument 1 = yop argument 2 = yep argument 3 = yap
Exemple de boucle For qui dézip tous les fichiers ziper d'un dossier:
$ for i in (find *.zip); unzip $i; end
Génère une suite de nombre entre 2 valeurs:
$ seq 1 5 1 2 3 4 5
repeatFor.sh
#!/bin/bash MOT=${1:?"Vous devez indiquer un mot"} NB=${2:-10} for i in $( seq 1 $NB ] ; do echo "$MOT" done
$chmod +x repeatFor.sh $ ./repeatFor.sh Bonjour 3 Bonjour Bonjour Bonjour
read.sh
#!/bin/bash while read ligne; do echo -n "Ma ligne : " echo $ligne done < $1
$ ./read.sh read.sh Ma ligne : #!/bin/bash Ma ligne : Ma ligne : while read ll; do Ma ligne : echo -n "Ma ligne : " Ma ligne : echo $ll Ma ligne : done < $1
La commande continue saute directement à l’itération / répétition suivante dans la boucle en n’effectuant pas les autres commandes restantes dans le cycle actuel de la boucle. Prenons tout de suite un exemple que nous allons commenter ensuite. Soit le script suivant que l’on appellera continue.sh
#!/bin/bash a=0 while [ "$a" -le 10 ]; do a=$(($a+1)) if [ "$a" -eq 2 ] || [ "$a" -eq 8 ] then continue # va directement à l’itération suivante de la boucle while fi echo -n "$a " # Cette partie ne sera pas exécutée pour a=2 et a=8 done
$ ./continue.sh 1 3 4 5 6 7 9 10
Nous voyons dans le résultat que ni 2 ni 8 ne sont affichés.
break.sh
#!/bin/bash a=0 while [ "$a" -le 10 ]; do a=$(($a+1)) if [ "$a" -eq 2 ] || [ "$a" -eq 8 ] then break # quitte directement la boucle while fi echo -n "$a " # Cette partie ne sera pas exécutée pour a supérieur ou égal à 2 done
$ ./break.sh 1
Nous voyons dans le résultat que la boucle s’arrête dès que la valeur de a est supérieure ou égale à 2. La commande break renvoi directement à la ligne done. La commande break peut aussi prendre en paramètre un niveau d’imbrication de boucle (paramètre numérique). Par exemple, break 3 va “terminer” trois boucles imbriquées.
La boucle for peut aussi prendre une syntaxe héritée du langage de programmation C. Cette variante est caractérisée par trois paramètres qui contrôlent la boucle for. Ces trois paramètres sont :
for (( EXP1; EXP2; EXP3 )) do command1 command2 command3 done
for3.sh
#!/bin/bash for ((i=1; i<=4; i++)); do echo "Nombre $i" done
$ ./for3.sh Nombre 1 Nombre 2 Nombre 3 Nombre 4
Ce que j'ai fait:
J'ai géré les nb de point d'ext comme: projet1.tar.gz → projet1_alice.tar.gz
#!/bin/bash nom_fichier=${1:?"Erreur : vous devez indiquer le nom du fichier a renommer"} nb_delimits=$(echo $nom_fichier | grep -o "\." | wc -l) nb_fields=$(expr $nb_delimits + 1) for i in $( seq 1 $nb_fields ) ; do if [ $i -eq 1 ] then new=$(echo $nom_fichier | cut -d . -f${i}) new=${new}_alice else new=$new.$(echo $nom_fichier | cut -d . -f${i}) fi done mv $nom_fichier $new
Ce qu'il fallais faire !
#!/bin/bash # fichier : tagalice.sh FULL_NAME=${1:?"Erreur : vous devez indiquer le nom du fichier à renommer"} #On va isoler le nom du fichier (partie avant le premier point) NAME=$(echo $FULL_NAME | cut -d. -f1) #On va isoler l'extension du fichier (partie apres le premier point) #NB: on considere qu'il y a toujours au moins un point dans le nom EXT=$(echo $FULL_NAME | cut -d. -f2-) #Construction du nouveau nom NEW_NAME="${NAME}_alice.$EXT" #On renomme le fichier mv "$FULL_NAME" "$NEW_NAME" ########################
Il faut les déclarer en début de script
nom_fonction() { commande1 commande2 ... }
Exemple : hello.sh
#!/bin/bash say_hello() { echo "Hello World !!!" } say_hello say_hello
$ chmod +x hello.sh $ ./hello.sh Hello World !!! Hello World !!! $
On utilise les même variables :
Exemple : modif de hello.shhello.sh
#!/bin/bash #définition de la fonction say_hello() { echo "Hello $1 !!!" } #utilisation de la fonction say_hello Me say_hello You
Quand on manipule une variable dans un script, les changements subis par cette variable valent pour l’ensemble du script. Et c’est aussi le cas pour les variables utilisées dans le code d’une fonction. Aussi, on dit que les variables sont globales au script, ou encore que la portée d’une variable est globale.
Il est cependant possible de limiter la portée d’une variable dont l’usage ne concerne que l’espace du corps d’une fonction. Cela permet d’éviter d’entrer en conflit avec les autres traitements du script.
Pour obtenir cette limitation il suffit d’utiliser la commande local. Cette commande doit se placer au début du code de la fonction, et elle prend en paramètre le nom de la variable concernée avec éventuellement la valeur de départ de celle-ci. :
local nom_variable ou local nom_variable=valeur
#!/bin/bash max() { if [ $1 -gt $2 ]; then return $1 else return $2 fi } IS_OK=${2:?"Vous devez fournir 2 valeurs"} max $1 $2 echo $?
Il existe 2 stratégies de contournement :
Amélioration du script afficheMax.sh
#!/bin/bash max() { if [ $1 -gt $2 ]; then echo $1 else echo $2 fi } IS_OK=${2:?"Vous devez fournir 2 valeurs"} REP=$(max $1 $2) echo $REP
$ alias alias ll=’ls -al’
La définition d’un alias suit la syntaxe suivante :
alias nomAlias="commande à exécuter"
La commande unalias supprime un alias existant.
$ unalias ll
Exemple d’utilisation d’une fonction que nous définissons dans le fichier .bashrc.
mkd() { mkdir -p "$@" && cd "$@" }
$ mkd /tmp/t/t/t/t/t/t/t/t/t $ pwd /tmp/t/t/t/t/t/t/t/t/t
Une bonne pratique est de séparer les fichiers contenant les alias et les fonctions en créant des fichiers .alias et .func et de rajouter dans le fichier .bashrc les lignes suivantes :
$ cat .bash [...] source .alias source .func [...]