Cours CMI / M1 Données - séance 1
Résumé de la séance 1
On y révise ce qu'est le système d'exploitation Linux avec ses principales commandes, dont ls, cat, head, tail, find, wc, grep, mkdir, gzip, gunzip, rm. Les scripts Bash, Perl et Python sont présentés de façon succinte.
1. Le système Linux
Linux est un système d'exploitation comme Windows ou Mac OS. Son but est de gérer l'ensemble des ressources matérielles (écran, clavier, mémoire, disque dur...) et logicielles (traitements de textes, tableurs, navigateurs, explorateurs de fichiers, jeux...).
Ce qui caractérise Linux est sa gratuité, la disponibilité de ses sources et son très grand nombre de développeurs et d'utilisateurs. De plus c'est un système complet prévu pour plusieurs utilisateurs et capable d'être serveur de nombreuses applications à distance (serveur Web, connexion utilisateurs, messagerie, serveur de fichiers distants...).
Si historiquement Linux s'utilisait en ligne de commandes via une console, Linux dispose aujourd'hui d'interfaces logicielles et de menus tout à fait comparables à ceux disponibles sur les ordinateurs Windows et Mac Intosh. Les menus et interfaces sont incomparables lorsqu'il s'agit de découvrir les possibilités d'un logiciel mais ils ont deux gros défauts : ils s'utilisent via le clavier et la souris (ce qui les rend difficilement automatisables) et ils sont visuels (ce qui fait qu'en général ils ne produisent aucun fichier de résultat pour conserver une trace de ce qui a été fait). De plus ils ne permettent pas toujours simplement de résoudre des problèmes simples, comme par exemple trouver les cinq derniers fichiers .txt écrits dans un répertoire donné. C'est pourquoi il est d'usage d'apprendre à utiliser la ligne de commandes sous Linux, réalisant ainsi une espèce de tchat avec le système d'exploitation.
Pour mémoire, si vous y êtes autorisé(e), la connexion au serveur forge se fait en local à la faculté des sciences d'Angers par
ssh -YC VOTRE_LOGIN_ICI@forge.info-uaPar contre, à l'extérieur du département informatique, la connexion au serveur forge doit se faire avec la commande
ssh -YC VOTRE_LOGIN_ICI@forge.info.univ-angers.frSi vous utilisez Windows, vous pouvez vous connecter au serveur forge à l'aide du logiciel putty qui est gratuit et téléchargeable à l'adresse officielle latest putty ou sur le site français putty 01.net.
Héritier des systèmes Unix les commandes de Linux peuvent être simples, comme cp pour copier des fichiers, ou excessivement techniques lorsqu'on les enchaine, comme par exemple la commande
ls -al | sort -n -r -k 5 -k 9 | head -n 20Il est donc conseillé de commencer en douceur avec les principales commandes Unix dont les 20 commandes usuelles listées ici avant d'essayer de maitriser les commandes de base pour ensuite connaitre les 101 commandes indispensables sous Linux.
Il restera enfin à pratiquer, pratiquer et pratiquer encore afin de devenir à l'aise avec toutes les subtilités des commandes Unix, de leur automatisation en shell, sachant que maitriser les commandes et comprendre le système de fichiers et les manipulations fichiers demande du temps.
Enfin, pour les plus courageuses et les plus courageux, on pourra tenter de choisir et installer un Linux sur son ordinateur, après avoir vérifié qu'on en maitrise bien les commandes fondamentales.
En particulier ce qu'on nomme la redirection des sorties permet de sauvegarder dans un fichier le texte produit par une commande et la redirection des entrées permet de lire dans un fichier ce qu'on devrait en principe taper au clavier, ce qui permet d'automatiser et de reproduire des traitements. Pour découvrir ce sujet, on pourra lire dans cet ordre les pages redir 1 et redir 2. Pour le maitriser, on viendra lire la page flux puis la page redirections.
2. Pratique des commandes Linux
Nous allons nous focaliser dans un premier temps sur les commandes : ls, cat, head, tail, find, wc, grep, mkdir, zip, unzip, rm.
Pour obtenir de l'aide sur l'une de ces commandes, il y a deux méthodes, à écrire dans le terminal. La première est man COMMANDE comme par exemple man ls ou man ls. La seconde est COMMANDE --help comme par exemple ls --help ou ls --help. Comme le montre le fichier ci-dessous, qui correspond au résultat de la commande ls --help, l'aide est parfois longue, avec des subtilités incompréhensibles pour un(e) débutant(e) :
Utilisation : ls [OPTION]... [FICHIER]... Afficher des renseignements sur les FICHIERs (du répertoire actuel par défaut). Trier les entrées alphabétiquement si aucune des options -cftuvSUX ou --sort ne sont utilisées. Les arguments obligatoires pour les options longues le sont aussi pour les options courtes. -a, --all ne pas ignorer les entrées débutant par . -A, --almost-all ne pas inclure . ou .. dans la liste --author avec -l, afficher l'auteur de chaque fichier -b, --escape afficher les caractères non graphiques avec des protections selon le style C --block-size=TAILLE convertir les tailles en TAILLE avant de les afficher. Par exemple, « --block-size=M » affiche les tailles en unités de 1 048 576 octets ; consultez le format de TAILLE ci-dessous -B, --ignore-backups ne pas inclure les entrées se terminant par ~ dans la liste -c avec -lt : afficher et trier selon ctime (date de dernière modification provenant des informations d'état du fichier) ; avec -l : afficher ctime et trier selon le nom ; autrement : trier selon ctime -C afficher les noms en colonnes --color[=QUAND] colorer la sortie ; QUAND peut être « always » (toujours, valeur par défaut si omis), « auto » (automatique) ou « never » (jamais) ; voir ci-dessous pour plus d'informations -d, --directory afficher les noms de répertoires, pas leur contenu -D, --dired générer une sortie pour le mode « dired » d'Emacs -f ne pas trier, activer -aU, désactiver -ls --color -F, --classify ajouter un indicateur (parmi */=>@|) aux entrées --file-type identique mais sans ajout de « * » --format=MOT « across » -x (croisé), « commas » -m (avec virgules), « horizontal » -x (horizontal), « long » -l (long), « single-column » -1 (une seule colonne), « verbose » -l (bavard), « vertical » -C (vertical) --full-time identique à -l --time-style=full-iso -g identique à -l mais sans afficher le propriétaire --group-directories-first regrouper les répertoires avant les fichiers ; peut être augmenté avec une option --sort, mais l'utilisation de --sort=none (-U) inhibe le regroupement -G, --no-group dans une longue liste, ne pas afficher les noms de groupes -h, --human-readable avec -l ou -s, afficher des tailles lisibles (par exemple 1K, 234M ou 2G) --si similaire, mais utiliser une puissance de 1 000 au lieu de 1 024 -H, --dereference-command-line suivre les liens symboliques en ligne de commande --dereference-command-line-symlink-to-dir suivre tous les liens symboliques en ligne de commande qui pointent vers un répertoire --hide=MOTIF ne pas afficher les entrées implicites correspondant au MOTIF de l'interpréteur (désactivé par -a ou -A) --hyperlink[=WHEN] hyperlink file names; WHEN can be 'always' (default if omitted), 'auto', or 'never' --indicator-style=MOT ajouter un indicateur de type à chaque entrée, en respectant le style indiqué par MOT : « none » (aucun suffixe, par défaut), « slash » (barre oblique, comme l'option -p), « file-type » (type de fichier, comme --file-type) ou « classify » (secret, comme l'option -F) -i, --inode afficher le numéro d'index de chaque fichier -I, --ignore=MOTIF ne pas afficher les entrées implicites correspondant au MOTIF de l'interpréteur -k, --kibibytes blocs de 1024 octets par défaut pour l'occupation d'espace disque -l utiliser le format long d'affichage -L, --dereference afficher les renseignements sur les fichiers référencés par les liens symboliques plutôt que sur les liens symboliques eux-mêmes -m remplir la largeur avec une liste d'entrées séparées par des virgules -n, --numeric-uid-gid identique à -l, mais afficher les valeurs numériques des UID et GID -N, --literal afficher les noms sans guillemets -o identique à -l mais sans afficher les informations de groupe -p, --indicator-style=slash ajouter l'indicateur « / » aux répertoires -q, --hide-control-chars afficher « ? » au lieu de caractères non graphiques --show-control-chars afficher les caractères non graphiques tels quels (par défaut sauf si le programme est « ls » et que la sortie s'effectue sur un terminal) -Q, --quote-name encapsuler chaque nom d'entrée entre guillemets --quoting-style=MOT utiliser le style d'encapsultation défini par MOT : literal, shell, shell-always, shell-always, shell-escape, shell-escape-always, c, escape -r, --reverse inverser l'ordre de tri -R, --recursive afficher récursivement les sous-répertoires -s, --size afficher la taille d'allocation de chaque fichier, en bloc -S trier selon la taille des fichiers, les plus grands au début --sort=MOT trier selon MOT au lieu du nom : « none » (aucun, -U), « size » (taille, -S), « time » (heure, -t), « version » (version, -v) ou « extension » (extension, -X) --time=MOT avec -l, afficher la date selon MOT au lieu de la date de modification par défaut : « atime », « access » ou « use » (-u), « ctime » ou « status » (-c) ; utiliser aussi la date indiquée comme clef de tri si --sort=time (le plus récent d'abord) --time-style=STYLE avec -l, afficher les dates selon STYLE : « full-iso », « long-iso », « iso », « locale » ou « +FORMAT » ; FORMAT est interprété comme dans « date » ; si FORMAT est FORMAT1<saut de ligne>FORMAT2, alors FORMAT1 s'applique aux fichiers non récents et FORMAT2 aux fichiers récents ; si STYLE est préfixé par « posix- », STYLE ne prend effet qu'en dehors des paramètres régionaux POSIX -t trier selon la date de modification, récent d'abord -T, --tabsize=COLS utiliser des tabulations à chaque COLS au lieu de 8 -u avec -lt, afficher et trier selon la date d'accès ; avec -l, afficher la date d'accès et trier par nom ; sinon trier selon la date d'accès, le plus récent d'abord -U ne pas trier, afficher les entrées dans l'ordre du répertoire -v tri naturel des numéros (de versions) dans le texte -w, --width=COLS définir la largeur de sortie à COLS. 0 signifie pas de limite -x afficher les entrées en ligne au lieu de colonne -X trier alphabétiquement selon les extensions des entrées -Z, --context afficher le contexte de sécurité de chaque fichier -1 afficher un fichier par ligne. Évite « \n » avec -q ou -b --help afficher l'aide et quitter --version afficher des informations de version et quitter L'argument TAILLE est un entier suivi d'une unité facultative (10k pour 10*1024 par exemple). Les unités sont K, M, G, T, P, E, Z et Y (puissances de 1024) ou KB, MB, etc. (puissances de 1000). L'utilisation de la couleur pour distinguer les types de fichiers est désactivée par défaut ainsi qu'avec --color=never (jamais). Avec --color=auto, ls émet des codes couleur seulement quand la sortie standard est connectée à un terminal. La variable d'environnement LS_COLORS peut modifier les paramètres. Utilisez la commande dircolors pour la définir. État de sortie : 0 en cas de succès, 1 en cas de problème mineur (comme impossible d'accéder à un sous-répertoire), 2 en cas de problème majeur (comme impossible d'accéder à un argument de ligne de commande). Aide en ligne de GNU coreutils : <http://www.gnu.org/software/coreutils/> Signalez les problèmes de traduction de « ls » à : <traduc@traduc.org> Documentation complète à : <http://www.gnu.org/software/coreutils/ls> ou disponible localement via: info '(coreutils) ls invocation'Avec man ls l'affichage se fait en mode page : on peut aller à la page suivante, à la page précédente et on en sort avec la touche q. Avec la touche h on voit que la navigation dans ces pages d'aide est sophistiquée...
Avec ls --help l'affichage se fait en continu. Il faut faire dérouler le contenu du terminal (mais comment ?) pour revoir l'aide.
Toutefois avec ls --help | more l'affichage se fait en mode page (simplifié). On en sort avec q.
Voici à quoi servent les commandes proposées :
commande indication explication_rapide ls list files affiche la liste des fichiers cat (concaténer) affiche le contenu de fichier(s) head (tête) affiche le début du contenu de fichier(s) tail (queue) affiche la fin du contenu de fichier(s) find (cherche) donne la liste des fichiers recherchés wc Word Count compte les mots, les lignes des fichiers grep wiki recherche des contenus de fichier(s) mkdir Make Directory crée un répertoire cd Change Directory va dans un répertoire zip (aller vite) compresse et archive rm remove supprime des fichiers Ce n'est bien sûr qu'avec de la pratique que l'on peut mémoriser ces commandes et leurs options.
On fera aussi bien attention aux caractères spéciaux pour les commandes :
caractère nom explication_rapide > supérieur redirection de la sortie < inférieur redirection de l'entrée | pipe ou tube enchainement des commandes avec E/S & é commercial exécution en tâche de fond A titre d'exercice, on exécutera les commandes suivantes, les unes après les autres. On commentera leur action. Volontairement, certaines commandes n'ont jamais été citées auparavant.
# allons-y ! mkdir Cmi cd Cmi pwd mkdir coursL2 cd coursL2 wget http://forge.info.univ-angers.fr/~gh/Cmi/linuxL2/linuxL2.zip unzip linuxL2.zip # oui, oui ! ls ls -al ls -alth
Afin de commenter les commandes, voici les lignes de commandes numérotées :
0001 # allons-y ! 0002 mkdir Cmi 0003 cd Cmi 0004 pwd 0005 mkdir coursL2 0006 cd coursL2 0007 wget http://forge.info.univ-angers.fr/~gh/Cmi/linuxL2/linuxL2.zip 0008 unzip linuxL2.zip # oui, oui ! 0009 ls 0010 ls -al 0011 ls -althLa ligne 1 n'est pas vraiment une commande, c'est juste un commentaire, utile pour les humains, ignoré par la machine.
La commande de la ligne 2 crée, à l'endroit où on tape la commande, un répertoire nommé Cmi. S'il existe déjà, on obtient un message d'erreur.
A la ligne 3, on va dans ce nouveau répertoire : le chemin courant est donc ce répertoire.
La commande de la ligne 4 affiche le chemin absolu de ce répertoire. pwd = Print Working Directory.
A la ligne 5, on crée un nouveau répertoire et grâce à la ligne 6, on se positionne dans ce répertoire.
A la ligne 7, on demande à Linux de rapatrier (télécharger) un fichier sur Internet dont on donne l'URL. C'est beaucoup plus court que de télécharger via un navigateur et d'aller rechercher le fichier dans le répertoire Téléchargements. On peut aussi s'en servir quand un navigateur affiche un lien : on fait un clic droit sur le lien et on sélectionne copier l'adresse du lien. Dans le terminal, on tape wget, un espace et un clic sur le bouton du milieu (qui réalise un "coller" à notre place) et le tour est joué !
La ligne 8 se compose d'une commande et d'un commentaire. Le commentaire est bien sûr ignoré. La commande, elle, décompresse l'archive qui vient d'être téléchargée.
Les lignes 9, 10 et 11 affichent la liste des fichiers du répertoire en mode compact, long et trié par date (avec affichage "humain").
Compléments :
les 80 premières pages du cours Unix en L2 du département informatique d'Angers.
les exercices corrigés de l'ENS (sauf partie programmation du shell).
3. Questions/réponses pour tester vos connaissances
Pour vous entrainer à la pratique du terminal, voici quelques commandes à lire (ou à déchiffrer ?) et quelques commandes à écrire pour des scénarios courants :
Question 3.1
Expliquer ce que font les commandes suivantes :
ls *.sql ls -al *sql ls -alt *sql ls -al | sort -n -r -k 5,5 | head -n 20Question 3.2
A quoi sert la commande locate ? Expliquer ce que fait la commande suivante :
locate officeQuestion 3.3
A quoi sert la commande find ? Quels sont ses paramètres ? Expliquer ce que fait l'enchainement de commandes suivant :
find . | grep -i "xls$"Question 3.4
Je voudrais faire une copie de sauvegarde du fichier listeProteines.txt et nommer la copie listeProteines_sov.txt. Quelle commande dois-je écrire ?
Question 3.5
Quelle commande Linux ne faut-il jamais écrire sous peine de perdre tous les fichiers de tous les répertoires ?
Question 3.6
Je voudrais créer une archive au format ZIP nommée sauvegardeExcel.zip de tous les fichiers Excel (formats xls et xlsx) du répertoire courant. Quelle commande dois-je écrire ? Et si j'avais voulu aussi sauvegarder tous les fichiers Excels de tous les sous-répertoires du répertoire courant (avec le chemin d'accès relatif), que faut-il modifier dans cette commande ?
Question 3.7
Je dois souvent aller dans mon répertoire ~/Tmp pour consulter les 5 derniers fichiers créés. Puis-je écrire un script nommé disons vatmp qui va dans ce répertoire et m'affiche les 5 derniers fichiers créés ?
Question 3.8
Qu'est-ce qu'un alias ? A quoi sert le fichier .bashrc ?
Question 3.9
J'aimerais connaitre le nom de toutes les tables de la base statdata et le nombre d'enregistrements des tables LEA.proteins et HSP.proteins. Quelles commandes MySQL faut-il écrire ? Je voudrais générer un fichier rapportTables.txt qui contient la date et l'heure puis les informations précédentes. Comment dois-je faire ?
Et si je voulais que le fichier soit automatiquement nommé d'après la date du jour, par exemple rapportTables.15_02_2014.txt, que faudrait-il écrire ?
Solutions : afficher les solutions
Réponse à la question 3.1
La commande ls liste les fichiers. Le paramètre *.sql indique que l'on ne veut voir que les fichiers dont le type est .sql (avec le point). Le paramètre *sql (donc sans le point) affiche les fichiers qui se terminent par sql. Par exemple le fichier test_mysql serait affiché avec cette deuxième commande, mais pas avec la première. Les options -al précise que l'on veut voir tous les fichiers, en mode long. Si on rajoute t, alors les fichiers sont triés par date.
La dernière commande affiche tous les fichiers puis les trie en mode numérique selon la cinquième information affichée et n'affiche que les 20 premiers fichiers correspondants.
Réponse à la question 3.2
La commande locate recherche dans l'ensemble de la configuration les fichiers enregistrés dans le système, donc principalement les fichiers d'installation. Le mot qui suit locate est ce que l'on cherche. Ici cela devrait afficher tous les fichiers de libreoffice, soit plusieurs milliers de fichiers, si l'on en croit les résultats de la commande locate office | wc -l.
Réponse à la question 3.3
Contrairement à locate, la commande find ne recherche que dans les répertoires qu'on lui spécifie. Ici c'est point donc le répertoire courant. find . recherche donc tous les fichiers du répertoire courant et de tous ses sous-répertoires. Ajouter grep -i "xls$" permet de restreindre l'affichage aux seuls fichiers qui se terminent par le mot xls, écrit en majuscules ou en miniscule. On aurait pu se contenter de l'option -name de find.
Réponse à la question 3.4
Il suffit d'utiliser la commande cp comme suit :
cp listeProteines.txt listeProteines_sov.txtRéponse à la question 3.5
La commande rm efface des fichiers, ce qui est toujours dangereux. Les options -rf forcent la destruction dans tous les répertoires, y compris en "forçant" la suppression des fichiers avec des droits de lecture seule. Et bien sûr, le paramètre * indique que l'on veut effacer tous les fichiers.
Donc la commande Linux à ne jamais écrire, sous peine de perdre tous les fichiers de tous les répertoires est :
rm -rf *Réponse à la question 3.6
La commande zip permet de créer des archives. On peut se contenter de
zip sauvegardeExcel.zip *.xls*pour archiver au format ZIP dans le fichier sauvegardeExcel.zip tous les fichiers Excel (formats xls et xlsx) du répertoire courant. Pour sauvegarder aussi les fichiers des sous-répertoires, il faut utiliser l'option -r.
Réponse à la question 3.7
Pour aller dans mon répertoire ~/Tmp la commande est cd ~/Tmp. Pour lister les 5 derniers fichiers créés, il faut utiliser la commande ls -alt | head -n 5. Il suffit donc d'écrire ces deux commandes dans le fichier vatmp, de rendre le fichier exécutable pour que Linux réalise automatiquement ces deux commandes.
# fichier vatmp cd ~/Tmp ls -alt | head -n 5Dans la mesure où la commande ls admet un paramètre de localisation, on peut se contenter d'une seule ligne de script :
Attention : à la sortie du script, on est revenu dans le répertoire de départ. C'est un comportement voulu par les concepteurs d'Unix.
# fichier vatmp2 ls -alt ~/Tmp | head -n 5Réponse à la question 3.8
Un alias permet de définir dans un terminal un mot comme synonyme d'une commande paramétrée ou d'un script. Par exemple pour disposer de la commande lsa comme synonyme de ls -al on peut écrire
alias lsa='ls -al'Comme un alias est défini uniquement pour la session en cours, si on ferme le terminal, on perd l'alias. Le fichier .bashrc est exécuté à chaque ouverture de terminal. Si on y met des alias, ceux-ci sont toujours disponibles.
Un alias qui exécute une commande cd est un moyen commode de changer rapidement de répertoire puisque, comme indiqué à la question précécente, un script standard exécuté "normalement" ne permet pas de le faire.
Réponse à la question 3.9
Les commandes MySQL à utiliser sont
use statdata ; show tables ; select count(*) from LEA.proteins ; select count(*) from HSP.proteins ;Pour les exécuter et produire le fichier résultat nommé rapportTables.txt, il suffit de mettre ces commandes dans un fichier, disons rapportTables.mysql et d'utiliser la redirection des entrées et des sorties, soit la commande :
mysql ... < rapportTables.mysql > rapportTables.txtPour que le nom du fichier contienne la date du jour, il faut passer par un script, par exemple un script shell comme le fichier rapportTables.sh suivant :
# (gH) -_- rapportTables.sh ; TimeStamp (unix) : 05 Mars 2016 vers 14:07 aujourdhui=`date '+%Y_%m_%d'` ; nomRapport="rapportTables.$aujourdhui.txt" ; sql -v -v -v < rapportTables.mysql > $nomRapport ; echo Vous pouvez consulter le rapport $nomRapport ;Pour exécuter ce script shell il suffit d'écrire :
sh rapportTables.sh4. Ecriture de scripts Bash, Perl et Python
Le but des exemples qui suivent est de montrer comment faire exécuter une plusieurs commandes par le système à l'aide d'un script. On fournit des script Bash dans un premier temps. Ensuite, pour montrer comment on peut exécuter des commandes systèmes en Perl et en Python , on fournit la traduction des scripts Bash en Perl et en Python. Comme ces exemples sont minimalistes, on pourra lire notre tuteur Perl et notre tuteur Python pour avoir une meilleure compréhension de ces langages.
Pour exécuter ces scripts depuis n'importe quel répertoire, on pourra écrire des alias ou modifier la variable d'environnement nommée PATH.
4.1 Scripts Bash élémentaires
Un script est «simplement» un ensemble de commandes paramétrées. On commence souvent par écrire des petits scripts sans paramètres comme raccourcis de commandes avant de demander aux scripts de réaliser des «choses intéressantes».
Script numéro 1 :
On veut être capable d'afficher le fichier ~/letters.txt où qu'on soit dans l'arborescence, juste en tapant letters.
Voici le code-source du script correspondant :
# fichier letters cat ~/letters.txtPour utiliser le script, il faut soit le rendre exécutable avec chmod +x letters, soit exécuter bash letters. La première solution est préférable. Mieux : si le fichier letters est dans le $PATH la commande letters est utilisable partout. On peut aussi utiliser un shebang.
Script numéro 2 :
On veut être capable d'afficher le fichier ~/letters.txt où qu'on soit dans l'arborescence, juste en tapant letters2. Avant d'afficher le fichier, Linux doit effacer l'écran.
Voici le code-source du script correspondant :
# fichier letters2 clear cat ~/letters.txtCe deuxième fichier est très peu différent du premier : on a juste ajouté la commande clear avant la commande cat.
Script numéro 3 :
Pour être sûr que le fichier linuxL2.zip est toujours à jour, on veut écrire un script majLinuxL2 qui zippe les nouveaux fichiers depuis le dernier archivage.
Après lecture de l'aide sur la commande zip, voici ce qu'on peut écrire :
# fichier majLinux2 cd linuxL2/ date > derniereSauvegarde zip -u linuxL2.zip *Si on ne crée pas de fichier, alors la commande zip peut ne rien afficher, ce qui peut être perturbant. Par contre, si l'archive est grosse, ce n'est pas une bonne idée de forcer un nouvel archivage si rien n'a changé. Il vaut mieux donc dans ce cas commenter la ligne qui exécute la commande date.
Script numéro 4 :
On veut afficher les 5 premiers et les 5 derniers messages du système (messages obtenus par la commande dmesg) via la commande dernMsg.
Il serait tentant de se contenter des commandes dmesg | head -n 5 et dmesg | tail -n 5 mais nous avons préféré indiquer la date et l'heure et aussi le numéro des messages (via grep -n).
# fichier dernMsg echo Premiers et derniers messages système en date du : echo -n " " date echo "" dmesg | grep -n "" | head -n 5 echo "" dmesg | grep -n "" | tail -n 5Script numéro 5 :
On veut fournir la valeur en centimètre du paramétre passé au script convpouces. S'il n'y a pas de paramètres, on affiche une aide explicite.
Malheureusement expr ne réalise pas de calculs autres que entiers. Il faut se tourner vers bc ou calc pour utiliser le script suivant :
## convpouces : conversion du paramètre en cm # si le paramètre n'existe pas, rappel de la syntaxe et sortie if [ -z $1 ] ; then # attention à ne pas écrire [-z $1] sans les espaces echo echo syntaxe : convpouces NB_DE_POUCES echo exemple : convpouces 10 # doit afficher 25.4 cm echo exit 1 fi # si le paramètre existe, on calcule et on affiche nbPouces=$1 nbCm=`calc 2.54 "*" $nbPouces` # autre solution : nbCm=`bc <<< "2.54 * $nbPouces" ` echo $nbPouces pouces font $nbCm cmCompléments : les TP corrigés cours Unix en L2 du département informatique d'Angers.
4.2 Scripts Perl élémentaires
Script numéro 1 :
Un script Perl pour afficher un fichier peut se contenter d'interfacer la commande cat ce qui se fait via l'utilisation de l'instruction system.
# # (gH) -_- letters.pl ; TimeStamp (unix) : 23 Février 2019 vers 13:35 system("cat ~/letters.txt") ;Une façon plus "évoluée" de ce script Perl consiste à mettre la commande à exécuter dans une variable, disons $cmd et de l'afficher avant de l'exécuter, soit le code :
# # (gH) -_- letters.pl ; TimeStamp (unix) : 23 Février 2019 vers 13:35 use strict ; use warnings FATAL => 'all'; my $cmd = "cat ~/letters.txt" ; print($cmd."\n") ; system($cmd) ;On notera ici qu'on force Perl à tester le code via les use et que la variable est "déclaréee" via my.
Script numéro 2 :
On pourrait croire qu'il suffit de mettre clear ; devant la commande cat mais ce serait une erreur, parce que l'affichage serait effacé. Donc le code suivant est incorrect :
# # (gH) -_- letters.pl ; TimeStamp (unix) : 23 Février 2019 vers 13:35 use strict ; use warnings FATAL => 'all'; my $cmd = "clear ; cat ~/letters.txt" ; print($cmd."\n") ; system($cmd) ;Voici une façon de faire qui montre l'expansion du symbole ~ (tilde) :
# # (gH) -_- letters.pl ; TimeStamp (unix) : 23 Février 2019 vers 13:35 use strict ; use warnings FATAL => 'all'; my $cmd = "cat ~/letters.txt" ; system("clear ; echo $cmd ; $cmd") ;Script numéro 3 :
Là encore, la solution la plus courte consiste à mettre les commandes du script 3 précédent dans une variable et à l'exécuter :
# # (gH) -_- majLinux2.pl ; TimeStamp (unix) : 23 Février 2019 vers 13:54 use strict ; use warnings FATAL => 'all'; my $cmd = "cd linuxL2/ ; date > derniereSauvegarde ; zip -u linuxL2.zip *" ; print($cmd."\n") ; system($cmd) ;Script numéro 4 :
Pour ce script, nous allons utiliser les backticks pour exécuter une commande et récupérer sa sortie, que nous affichons dans la foulée :
# # (gH) -_- dernMsg.pl ; TimeStamp (unix) : 23 Février 2019 vers 13:58 use strict ; use warnings FATAL => 'all'; print "Premiers et derniers messages système en date du : ".`date`."\n" ; system("dmesg | grep -n '' | head -n 5") ; print("[...]\n" ) ; system("dmesg | grep -n '' | tail -n 5") ;Script numéro 5 :
Dans ce dernier script, on vérifie au passage que le paramètre passé est un nombre entier via une expression régulière :
# # (gH) -_- convpouces.pl ; TimeStamp (unix) : 23 Février 2019 vers 14:03 use strict ; use warnings FATAL => 'all'; ## convpouces : conversion du paramètre en cm # si le paramètre n'existe pas, rappel de la syntaxe et sortie if ($#ARGV == -1) { print "syntaxe : perl convpouces.pl NB_DE_POUCES\n" ; print "exemple : perl convpouces.pl 10 # doit afficher 25.4 cm \n" ; exit(1) ; } ; # fin si # si le paramètre existe, on teste que c'est bien un entier # si c'est le cas, on calcule et on affiche my $nbPouces = $ARGV[0] ; if ($nbPouces !~ /^[0-9]+$/) { print "Pas de conversion possible, vous n'avez pas entré un nombre entier.\n" ; } else { my $nbCm = 2.54 * $nbPouces ; print "$nbPouces pouces font $nbCm cm\n" ; } ; # finsiPour éviter d'écrire !~ il est possible de recourir à unless afin d'utiliser la syntaxe classique =~ :
# # (gH) -_- convpouces.pl ; TimeStamp (unix) : 23 Février 2019 vers 14:03 use strict ; use warnings FATAL => 'all'; ## convpouces : conversion du paramètre en cm # si le paramètre n'existe pas, rappel de la syntaxe et sortie if ($#ARGV == -1) { print "syntaxe : perl convpouces2.pl NB_DE_POUCES\n" ; print "exemple : perl convpouces2.pl 10 # doit afficher 25.4 cm \n" ; exit(1) ; } ; # fin si # si le paramètre existe, on teste que c'est bien un entier # si c'est le cas, on calcule et on affiche my $nbPouces = $ARGV[0] ; unless ($nbPouces =~ /^[0-9]+$/) { print "Pas de conversion possible, vous n'avez pas entré un nombre entier.\n" ; } else { my $nbCm = 2.54 * $nbPouces ; print "$nbPouces pouces font $nbCm cm\n" ; } ; # finsi4.3 Scripts Python élémentaires
Script numéro 1 :
Un script Python pour afficher un fichier peut se contenter d'interfacer la commande cat ce qui se fait via l'utilisation de la méthode os.system, ce qui oblige à "importer" le module os :
# # (gH) -_- letters.py ; TimeStamp (unix) : 23/01/2019 vers 17:36 import os os.system("cat ~/letters.txt") ;Une façon plus "évoluée" de ce script Python consiste à mettre la commande à exécuter dans une variable, disons cmd et de l'afficher avant de l'exécuter, soit le code :
# # (gH) -_- letters2.py ; TimeStamp (unix) : 20/01/2019 vers 13:35 from os import system cmd = "cat ~/letters.txt" print(cmd) system(cmd)On notera ici qu'on a juste importé la méthode dont on a besoin et qu'on l'a utilisée comme une fonction.
Script numéro 2 :
La solution Python est très semblable à la solution Perl :
# # (gH) -_- letters.py ; TimeStamp (unix) : 11/02/2019 vers 13:35 import os cmd = "cat ~/letters.txt" ; os.system("clear ; echo " + cmd + " ; " + cmd) ;Script numéro 3 :
Là encore, la solution Python ressemble beaucoup à la solution Perl (à moins que ce ne soit l'inverse) :
# # (gH) -_- majLinux2.pl ; TimeStamp (unix) : 18 Janvier 2019 vers 13:54 import os cmd = "cd linuxL2/ ; date > derniereSauvegarde ; zip -u linuxL2.zip *" print(cmd) os.system(cmd)Script numéro 4 :
Afin de capturer la sortie d'une commande système, nous utilisons le module subprocess :
# -*- coding:latin1 -*- # # (gH) -_- dernMsg.py ; TimeStamp (unix) : 05 Mars 2019 vers 15:21 from os import system import subprocess dateEtHeure = subprocess.run("date", stdout=subprocess.PIPE) print("Premiers et derniers messages système en date du : "+dateEtHeure.stdout.decode()) system("dmesg | grep -n '' | head -n 5") ; print("[...]\n" ) ; system("dmesg | grep -n '' | tail -n 5") ;Script numéro 5 :
Dans ce dernier script, on vérifie aussi que le paramètre passé est un nombre entier via une expression régulière :
# -*- coding:latin1 -*- # # (gH) -_- convpouces.py ; TimeStamp (unix) : 23 Février 2019 vers 18:16 import sys import re # aide éventuelle if (len(sys.argv)==1) : aide = ''' syntaxe : python3 convpouces.py NOMBRE_ENTIER exemple : python3 convpouces.py 7 ''' print(aide) sys.exit() # fin de si # on veut un entier, soit l'expression régulière "^[0-9]+$" nbPouces = sys.argv[1] if not re.search("^[0-9]+$",nbPouces) : print("Pas de conversion possible, vous n'avez pas entré un nombre entier.") else : nbCm = 2.54 * int(nbPouces) print(str(nbPouces) + " pouces font "+ str(nbCm) +" cm") ; # fin si5. Un script moins élémentaire en Bash
Enfin un exercice utile (!) : on voudrait dénombrer le nombre de règnes présents dans le fichier lea.tsv listé ci-dessous :
Voici ce qu'on doit obtenir :
there are 7 reigns: 1:Alveolata 2:Bacteria 3:Euryarchaeota 4:Fungi 5:Metazoa 6:Parabasalidea 7:ViridiplantaeOn utilisera les commandes cut, tail, sort, wc et grep.
Serait-ce plus difficile avec les fichiers lea.csv ou lea.dar ?
On pourra utiliser les fichiers minilea.tsv, minilea.csv et minilea.dar pour tester les commandes.
Serait-il envisageable de compter combien de fois chaque règne est vu dans le fichier ?
Le fichier lea.tsv est un fichier dont les informations sont séparées par des tabulations. Pour récupérer juste la troisième information, il faut utiliser cut -f 3. La ligne 1 ne contient pas des données mais le nom des colonnes. Il faut l'ignorer à l'aide de tail -n +2. Pour garder les noms de règnes différents, on peut se contenter de sort -u. On peut ensuite compter grâce à wc -l. Un affichage numéroté des règnes peut être obtenu via grep -n ''. On trouvera ci-dessous le script regnes qui fournit l'affichage demandé :
## comptage et listage des règnes taxonomiques (colonne 3) dans le fichier lea.tsv # il faut sauter la ligne 1 (nom des colonnes) cut -f 3 lea.tsv | tail -n +2 | sort -u > regnes.lst echo there are $(wc -l regnes.lst | cut -d ' ' -f 1) reigns: grep -n '' regnes.lstC'est à peine plus compliqué pour les autres fichiers lea.csv et lea.dar dont les séparateurs sont respectivement la virgule et les espaces [multiples]. Les solutions associées sont nommées regnes2 et regnes3.
## comptage et listage des règnes taxonomiques (colonne 3) dans le fichier lea.csv # il faut sauter la ligne 1 (nom des colonnes) cut -d "," -f 3 lea.csv | tail -n +2 | sort -u > regnes2.lst echo there are $(wc -l regnes.lst | cut -d ' ' -f 1) reigns: grep -n '' regnes2.lst## comptage et listage des règnes taxonomiques (colonne 3) dans le fichier lea.dar # il faut sauter la ligne 1 (nom des colonnes) tr -s ' ' < lea.dar | cut -d ' ' -f 3 | tail -n +2 | sort -u > regnes3.lst echo there are $(wc -l regnes.lst | cut -d ' ' -f 1) reigns: grep -n '' regnes3.lstIl est envisageable de compter combien de fois chaque règne est vu dans le fichier dans un script Bash, mais cela demande une grande technicité. Utiliser des structures de données nommées dictionnaires, hash tables ou tableaux associatifs, évidemment disponibles en Perl et en Python, est une solution beaucoup plus simple et plus facile à écrire.
Cliquer ici pour revenir à la page de départ des cours CMI / M1.
Retour à la page principale de (gH)