Il suffit de taper les deux noms de fichiers à la suite; par exemple, pour visualier bla puis blo, on tape :
cat bla blo
On demande à cat d'afficher le contenu d'un fichier, puis de placer le résultat dans un fichier :
cat toto > copie
On demande à cat de rediriger sa sortie dans un fichier, puis on n'a plus qu'à taper le texte et à indiquer la fin du texte avec ^D :
galion ~ $ ls maitrise.tex galion ~ $ cat > notes Faire la bibliographie Revoir le chapitre 1. ^D galion ~ $ ls maitrise.tex notes galion ~ $ cat notes Faire la bibliographie Revoir le chapitre 1. galion ~ $
C'est bien sûr un moyen un peu spartiate pour écrire du texte, mais dans le cas de choses très courtes dans ce style, ce peut être plus rapide que de lancer un véritable éditeur.
cat bla blo > blu
et
cat bla blo >> blu
Que se passe-t-il, pour chaque ligne, selon que le fichier blu existe ou n'existe pas ?
cat bla blo > blu
concatène les deux fichiers bla et blo, et place le résultat dans un nouveau fichier appelé blu. Si blu existe déjà, le shell affiche un message d'erreur et ne fait rien.
cat bla blo >> blu place la concaténation de bla et blo à la fin d'un fichier blu déjà existant. S'il n'existe pas, le shell affiche un message d'erreur et en reste là, sans créer de fichier blu.
Les deux redirections ne sont donc pas du tout équivalentes, mais leur action dépend du shell, qui a des options qui modifie leur comportement par défaut.
Il faut utiliser l'option -n de cat. Par exemple :
galion ~ $ cat bla Pomme Poire Prune galion ~ $ cat -n bla > blo galion ~ $ cat blo 1 Pomme 2 Poire 3 Prune galion ~ $
Il s'agit de donner le nom des fichiers en indiquant qu'ils commencent par essai et qu'ils finissent par un chiffre. Il y a en fait plusieurs façons de faire :
Ici, on trouvera tous les fichiers commençant par essai, suivi d'un unique caractère qui peut ne pas être un chiffre.
On commande par créer un répertoire C avec mkdir, puis, avec mv, on déplace tous les fichiers ayant un suffixe . et dont le nom est fait d'une suite de caractères quelconques :
galion ~ $ ls hello* zoinx* hello.c zoinx.c galion ~ $ mkdir C galion ~ $ mv *.c C/ galion ~ $ ls C/ hello* zoinx* galion ~ $ ls C/ hello.c zoinx.c
On commence par créer le répertoire Rangement avec mkdir. Pour désigner les noms des fichiers, il faut indiquer la notion de «minuscule». On pourrait écrire explicitement l'alphabet entre crochets, pour dire «l'un de ces caractères», puis faire de même avec les majuscules. Mais on gagne du temps en utilisant des intervalles ([a-z] et [A-Z]). Le reste du nom du fichier, avant et après la minuscule puis la majuscule, est indéfini. On écrit donc :
galion ~ $ mkdir Rangement galion ~ $ mv *[a-z][A-Z]* Rangement/
Le principe est le même, sauf que l'on indique explicitement les voyelles entre crochets :
galion ~ $ mkdir Rangement galion ~ $ mv *[aeiou][aeiou][aeiou]* Rangement/
On peut procéder de deux façons : utiliser ls seul et des jokers, ou rediriger ls dans grep et utiliser les expressions régulières de grep.
Dans la suite du corrigé, on suppose que l'on se trouve déjà dans /bin/.
On met des apostrophes autour des expressions de grep pour les protéger contre le shell. Enfin, on ne détaille pas les expressions régulières; à noter ces points importants à propos de grep :
On constate que grep est plus complexe mais bien plus puissant que les jokers du shell.
Avec ls seul | Avec ls et grep | ||
Commence par «a» et dont la deuxième lettre est «s» ou «t» | ls a[st]* | ls | grep '^a[st].*' | |
Contient «un» et se termine par «t» | ls *un*t | ls | grep '.*un.*t$' | |
Contient «gre» ou «st» | ls *(gre|st)* | ls | grep '\(gre\|st\)' | |
Contient exactement deux lettres «m» | ls | grep '[^m]*m[^m]*m[^m]*' | ||
Contient au moins deux lettres «m» | ls | grep '.*m.*m.*' | ||
Contient au moins quatre caractères et aucun chiffre | ls | grep '^[^0-9]\{4,\}$' | ||
Est constitué de deux lettres exactement | ls ?? | ls | grep '^..$' | |
Commence et finit par un chiffre | ls [0-9]*[0-9] | ls | grep '^[0-9].*[0-9]$' |
Une ligne vide est différente d'une ligne ne contenant que des blancs, c'est-à-dire des espaces ou des tabulations, même si pour un oeil humain cela revient au même. La commande de recherche sera différente selon le cas :
grep '^$' fichier
grep '^[[:space:]]$' fichier
Pour éliminer toutes les lignes blanches pour un oeil humain, on combine les deux expressions et on utilise l'option -v qui inverse le sens de la recherche. On n'a plus qu'à rediriger la sortie dans un fichier. On écrit donc :
grep -v '\(^[[:space:]]$\|^$\)' fichier1 > fichier2
en remplaçant éventuellement le motif par '^$' ou ^[[:space:]]$' selon que l'on veut ôter les lignes vides ou les lignes contenant des blancs.
On cherche la chaîne de caractère «mine», qui soit un mot, éventuellement suivi d'un «s». On va donc désigner le début du mot avec le symbole \<, la fin du mot avec le symbole \>, et le «s» optionnel avec le point d'interrogation. On veut aussi faire apparaître le nombre d'occurences du mot, dans chaque fichier du répertoire zola, avec l'option -c de grep.
Les noms des fichiers de Germinal sont de la forme zola1.txt, de 1 à 6. Pour chercher dans tous les fichiers de cette sorte, on peut écrire, au choix (attention à ne pas confondre les wildcards du shell avec les expressions régulières de grep).
On peut donc écrire :
grep -c '\<mines?\>' *.txt
Et on obtient :
zola1.txt:5 zola2.txt:0 zola3.txt:3 zola4.txt:3 zola5.txt:1 zola6.txt:2
Attention : les chiffres indiqués correspondent au nombre de lignes où figure le mot «mine», mais pas au nombre réel d'occurences du mot. Pour un mot précis comme celui-ci, la marge d'erreur est faible, mais si vous cherchez un article défini, par exemple, cette méthode est insuffisante. C'est là qu'un langage comme Perl est très utile.
Une ligne blanche, c'est rien entre un début de ligne et une fin de ligne, ou alors une ligne ne contenant que des espaces et des tabulations. On va donc chercher toutes les lignes correspondant à ce schéma (voir plus haut pour ces questions de définitions). Comme il y a deux motifs à chercher, on utilise l'expression régulière qui permet de chercher un motif ou un autre :
\(motif1\|motif2\)
La commande à taper est :
grep '\(^[[:space:]]$\|^$\)' zola1.txt
Ensuite, on veut compter le nombre de lignes ainsi produites par grep, avec la commande wc (word count); on va utiliser l'option -l (lines, lignes). On tape donc :
grep '\(^[[:space:]]$\|^$\)' zola1.txt | wc -l
Et on obtient «81». Bien évidemment, on aurait pu se rappeler que l'option -c de grep donne le nombre de lignes matchant la chaîne recherchée, et obtenir le même résultat en ne lançant qu'un seul processus...
À propos du fichier /etc/hosts : les ordinateurs sur l'Internet sont désignés par une adresse IP, constituée de 4 nombres entre 0 et 255 séparés par des points. C'est cette adresse IP qui permet à un ordinateur d'envoyer un message (datagramme IP) à un autre.
Cependant, mémoriser les adresses IP n'est pas commode pour un humain. Pour cette raison, les ordinateurs ont aussi un «nom», constitué d'un nombre variable de composantes séparées par des points (par exemple, research.att.com).
Le mécanisme de conversion d'un nom en adresse IP (ou le mécanisme inverse) s'appelle la «résolution de noms». Elle se fait normalement par l'intermédiaire de nameservers, ordinateurs sur lequel tourne le programme BIND, qui se chargent de répondre aux questions de résolution de noms.
Cependant, pour certaines machines très communément accédées depuis un ordinateur donné (par exemple, les machines de la même salle) ou bien pour éviter d'avoir à configurer un nameserver, on préfère parfois utiliser le fichier /etc/hosts : celui-ci définit un certain nombre de conversions nom -> adresse IP qui seront consultées avant les nameservers.
La bibliothèque qui se charge de faire la traduction, et qui consulte d'abord le /etc/hosts puis les nameservers, s'appelle la libresolv.
head -15 /etc/hosts
tail -15 /etc/hosts
tail +15 /etc/hosts
head -20 /etc/hosts | tail -6
Il y a deux solutions :
head -9 fichier | tail -5
tail -8 fichier | head -5
On utilise la commande head pour extraire les cinq premières lignes du fichier, puis la commande tail pour ne conserver que la dernière des cinq :
head -5 fichier | tail -1
C'est la commande sort qui permet de trier des fichiers selon un ordre donné.
sort sans option trie automatiquement en fonction du premier caractère, par ordre alphabétique si c'est une lettre, par ordre croissant si ce sont des chiffres. Il suffit donc de taper :
sort fichier
Pour cela, sans utiliser d'éditeur, on peut utiliser la commande cut, qui élimine des champs dans une ligne. Par défaut, le séparateur de champs est une tabulation. Ici, on peut demander à cut de considérer le slash comme un séparateur de champs (option -d, «délimiteur»), et de ne conserver que le deuxième champ du fichier (option -f, field). On redirige ensuite la sortie dans un autre fichier :
cut -d/ -f2 fichier > fichier2
sort -r fichier2
La réponse n'est pas simple, car vous avez également des répertoires de configuration, comme .netscape/ qui contient entre autres vos marque-pages (bookmarks.html), vos préférences (preferences), etc. On va compter le nombre de fichiers commençant par un point situés dans votre répertoire principal, en éliminant les copies de sauvegarde (qui finissent par un tilde). Il y a plusieurs manières de procéder.
On peut penser à une solution complexe et bien lourde utilisant toutes ces commandes, ce qui permet de les apprendre plus qu'autre chose... On affiche une liste longue avec l'ensemble des fichiers (ls -la) puis qui élimine tous les répertoires et les liens avec grep en ne gardant que les lignes qui commencent par un tiret :
ls -al | grep '^-'
Ensuite, on utilise tr pour ne conserver qu'un seul espace entre chaque champ de la liste, en utilisant l'option -s (squeeze) qui remplace par une seule occurence la répétition d'un caractère spécifié; on met des apostrophes autour de l'espace pour qu'il soit compris comme tel et non comme un simple espace :
tr -s ' '
On utilise cut pour conserver le dernier champ avec les noms de fichiers (en l'occurence le neuvième champ), en indiquant que l'espace sert de délimiteur de champ :
cut -d' ' -f9
Enfin, on demande à grep de ne retenir que les fichiers commençant par un point, et ne finissant pas par un tilde, et on les comptel'option -c de grep. Cela donne pour finir :
ls -al | grep '^-' | tr -s ' ' | cut -d' ' -f 9 | grep -c '^\..*[^~]$'
Mais que de tourments pour si peu... :-)
Il y a plus simple... On demande à ls une liste des fichiers commençant par un point (avec l'option -d pour ne pas descendre dans les répertoires de configuration), on ne garde que les lignes ne finissant pas par un / ou un tilde, et on compte :
ls -ad .* | grep -vc '\(~\|/\)$'
On demande à find de chercher dans le répertoire courant (.), sans descendre dans l'arborescence (-maxdepth 1), tous les fichiers normaux (-type f : file), dont le nom commence par un point (-name '.*'). On les compte ensuite avec wc :
find . -maxdepth 1 -name '.*' -type f | wc -l
Cette solution est préférable car elle ne lance que deux processus et non pas au moins cinq comme la précédente.
Il y a deux solutions, l'une faisant appel à ls et grep, l'autre faisant appel à find.
Le principe est le même que dans l'exercice précédent. La différence est que grep va chercher les lignes qui commencent par un point et finissent par un slash. Cela se fait de la manière suivante :
grep '^\..*/$'
.* signifie «n'importe quel caractère (point) répété zéro ou plusieurs fois (étoile)».
On tape donc :
ls -ad .* | grep '^\..*/$' | wc -l
On part ici du principe que vous avez un alias de ls sur ls -F (qui met un slash après les noms de répertoires, une étoile après les noms d'exécutables et une arobase après les noms de liens). Si ce n'est pas le cas, ajoutez-le dans un fichier .alias ou tapez ls -lF.
On demande à find de chercher tous les fichiers de type «répertoire» (-type d : directory), et dont le nom commence par un point (-name '.*', les quotes servant à protéger du shell le contenu de l'expression), dans descendre dans l'arborescence.
On tape donc :
find . -maxdepth 1 type d -name '.*' | wc -l
Il y a une inexactitude dans le résultat : find compte aussi ./ dans le résultat.
C'est l'option -R de ls qui permet d'afficher récursivement le contenu d'un répertoire et de ses sous-répertoires (à ne pas confondre avec -r qui inverse le tri). Pour rediriger la sortie d'une commande dans un fichier, on utilise le caractère >. Pour mettre la liste de tous les fichiers de l'arborescence dans un fichier toto, il faut donc taper :
ls -R > toto
Il va s'agir de faire une liste récursive de l'ensemble de votre compte (option -R de ls), incluant les fichiers de configuration (option -a) et les renseignements donnés par l'option -l.
De la longue liste obtenue, on ne veut retenir que les fichiers, dont les droits commencent par un tiret (un d identifie les répertoires). On va donc demander à grep de chercher toutes les lignes commençant par un tiret.
Enfin, on va placer le résultat dans un fichier appelé liste. On tape donc :
ls -alR | grep '^-' > liste
L'option -l de ls donne une liste longue des fichiers, incluant les droits et le type des fichiers, identifiés par une lettre : rien pour un fichier, «d» pour un répertoire (directory), «l» pour un lien (link); par exemple :
drwxr-xr-x 2 emilia users 1024 mai 10 02:27 www/
Pour obtenir la liste des fichiers du répertoire courant qui sont des liens symboliques, il suffit donc d'afficher cette liste longue et de ne retenir que les lignes qui commencent par un «l», grâce à la commande grep. On utilise une expression régulière pour cela : le chapeau (^) désigne le début de la ligne, et l'ensemble de l'expression est placée entre apostrophes pour qu'elle ne soit pas interprétée par le shell. On tape donc :
ls -l | grep '^l'
Il faut lancer le man de less, et ensuite chercher dedans le nombre de lignes contenant le mot file («fichier» en anglais), avec grep. C'est l'option -c (count) de grep qui va servir.
Finalement, on écrit :
man less | grep -c file
Et on obtient 205. C'est le nombre de lignes contenant au moins une fois la chaîne de caractères file, mais pas le nombre d'occurences du mot dans le fichier : il pourrait y avoir plusieurs fois file sur la même ligne. On atteint là encore la limite de ce que sait faire grep.
Il faut d'abord faire une liste des fichiers avec leurs tailles (option -l de ls. Ensuite, il faut trier ces lignes en fonction de la taille, avec la commande sort. Une ligne est de la forme suivante :
-rwxr-xr-x 1 root staff 5872 Jan 21 1994 /usr/bin/rm*
C'est le cinquième champ, celui de la taille, qui nous intéresse. La numérotation commençant à 0 (comme les étages), pour indiquer le cinquième champ on écrit +4. Ensuite, on veut que le tri se fasse selon un critère numérique (option -n) et à l'envers, en commençant par les plus grandes valeurs (option -r, reverse).
Pour finir, on veut les dix premières lignes du résultat. On les sélectionne avec la commande head; par défaut, elle prend les dix premières lignes d'un fichier, il n'est donc pas nécessaire de préciser le nombre de lignes voulues. Finalement, on écrit :
ls -l /usr/bin | sort -nr +4 | head
Une manière de résoudre cet exercice consiste à utiliser le programme
sed
qui sert à manipuler du texte.
Nous allons utiliser la commande s
de sed
.
Sa syntaxe est la
s/regexp/remplacement/
où regexp est une expression régulière et remplacement une chaîne devant la remplacer.
sas ~ $ cat /etc/hosts | sed -e "s/^.\{4\}\(.\).*/\1/"
Le "^.\{4\}"
du début sert à filtrer les
4 premiers caractères de chaque ligne. Ensuite, \(.\)
filtre
n'importe quel caractère, le fait de mettre des parenthèses enregistre le
caractère en question dans une variable que l'on peut utiliser dans
la chaîne de remplacement avec "\1"
. Ensuite,
.*
filtre le reste de la ligne.
sas ~ $ cat /etc/hosts | sed -e "s/^.\{4\}\(.\{6\}\)..\(.\).*/\1 \2/"
sas ~ $ cat /etc/hosts | sed -e "s/^.\{14\}//"
Les pages jaunes (yellow pages) sont un système qui centralise certaines bases de données communes à toutes les machines du système (logins et noms utilisateurs, mots de passes, groupes d'utilisateurs, noms et adresses des autres machines sur le réseau) sur un petit nombre de serveurs redondants; cela permet de garder des bases de données cohérentes, plus facilement que si on devait mettre à jour leur contenu sur plusieurs centaines de machines à la fois.
On dit plutôt aujourd'hui NIS ou Network Information System, Yellow Pages étant une marque déposée de British Telecom.
La commande ypcat permet de visualiser une base de données: citons en particulier: ypcat passwd, ypcat group, ypcat hosts.
Ces bases de données sont les versions centralisées des fichiers /etc/passwd, /etc/group et /etc/hosts, lesquels ne contiennent alors plus que quelques informations; par exemple, le fichier /etc/hosts contient tout de même des adresses de machines, ne serait-ce que celle du serveur de pages jaunes....
Pour avoir une liste de tous les comptes, on tape
ypcat passwd
On veut ensuite sélectionner les gens dont le répertoire personnel contient /96/, et dont le login commence par l, et compter le nombre de lignes (option -c de grep). On tape donc :
ypcat passwd |grep c '^l.*/96/'
et on obtient 19.
On veut savoir si des chemins d'accès de répertoires personnels sont de la forme
/users/8[0-9]
On tape donc :
ypcat passwd | grep '/users/8[0-9]'
On veut avoir une liste des gens dont le chemin d'accès du répertoire personnel commence par /users/ et un numéro : /users/9[0-9] (puisqu'on vient de voir qu'il n'y a pas de gens des promotions antérieures). On utilise l'option -c (count) pour avoir le nombre de personnes :
ypcat passwd | grep -c '/users/9[0-9]/'
Le numéro d'ID (user identification) identifie les utilisateurs, les numéros les plus bas correspondant au système (l'UID de root est 0). C'est le troisième champ, les champs étant séparés par des deux-points.
On va utiliser sort pour trier, selon un critère numérique (option -n). Par défaut, avec sort les champs sont délimités par des blancs, il faut donc indiquer qu'ici ce sont des deux-points, avec l'option -t. Enfin, on trie en fonction du troisième champ (2, la numérotation commençant à 0).
On suppose aussi que l'on veut pouvoir lire le résultat du tri avec less. On tape donc :
ypcat passwd | grep '/users/9[0-9]' | sort -n -t: +2 | less
grep
pour ne garder que les lignes des pages
jaunes correspondant aux personnes ayant zsh
comme shell de
login et on utilise sed
pour n'afficher que le login :
bireme ~ $ ypcat passwd | grep "zsh$" | sed -e "s/:.*//"
clipper
, tout le
monde à /bin/sh
comme shell de login. Le shell (en général
zsh
) n'est lancé qu'à partir du script
.profile
. Il s'agit d'un choix de l'administrateur système.
bireme ~ $ ypcat passwd | sed -e "s/:\/.*//
s/.*://" | grep " .*[aeiou][aeiou].*"
C'est la commande df qui donne des informations sur le disque et sur les partitions montées. Pour rediriger la sortie d'une commande dans un fichier, on utilise l'opérateur de redirection > suivi du nom du fichier. Dans notre cas, pour conserver les informations dans un fichier appelé disque, on écrira :
df > disque
C'est la commande finger qui donne des renseignements sur les utilisateurs. Si on tape
finger martin
ou mieux (plus rapide),
finger -m martin
les renseignements concernant l'utilisateur s'affichent. On y trouve la date de son dernier login sur la machine où vous êtes, ainsi que la date de la dernière fois où il a lu son courrier (mais ce à condition qu'il ait reçu du courrier depuis...).
C'est la commande file qui permet d'afficher le type des fichiers. Dans notre cas, il suffit d'écrire:
galion ~ $ file /etc/passwd /usr/include/stdio.h /bin/ls . /etc/passwd: ASCII text /usr/include/stdio.h: C program text /bin/ls: ELF 32-bit MSB executable, SPARC, version 1, stripped .: directory galion ~ $