4 - bash

Chemin relatif et chemin absolu

Un chemin est une suite de répertoires.

Il permet de se rendre du répertoire courant jusqu’au répertoire de destination ou d’accéder à un fichier.

Le chemin absolu commence TOUJOURS par /. Il permet de se rendre dans un répertoire depuis la racine.

Le chemin relatif ne commence JAMAIS par /. Il permet de se rendre dans un répertoire depuis l’emplacement courant.

Le . le répertoire courant.

Le .. le répertoire parent (au-dessus) du répertoire courant.

Dans un chemin relatif, le premier répertoire du chemin est cherché dans le répertoire courant.

Exemples

Depuis /home/<user>/Documents se rendre dans /home/<user>:

Chemin relatif:

$ cd .. 

Chemin absolu

$ cd /home/<user>

Depuis /home/<user> se rendre dans /etc:

Chemin relatif

$ cd ../../etc

Chemin absolu

$ cd /etc

Que se passe-t-il si vous êtes à la racine / et que vous tapez cd ..?

  • Vous ne bougez pas, il n’y a rien au dessus de /.

Quelle est l’erreur dans le chemin /../usr/./bin?

  • Il n’y a pas d’erreur, les points sont ignorés dans un chemin absolu.

Est-ce un chemin relatif ou un chemin absolu?

  • Absolu, il commence par /.

Où ce chemin vous conduit-il?

  • /usr/bin

Et /usr/../../bin?

Les variables

En bash il est possible de définir des variables. Certaines variables sont définies par le système au démarrage ou à l’ouverture de la session, ce sont les variables d’environnement.

Pour afficher la liste des variables d’environnement:

$ [prompt]$ $-TAB-TAB

L’utilisateur peut créer ou modifier ses propres variables à l’aide de l’instruction (notez qu’il n’y a pas de $ au début du nom de la variable et pas de ‘ ’ autour du = :

$ variable=valeur

Pour accéder au contenu de la variable, il faut préfixer le nom de la variable par un $ :

$ echo $variable

Une variable peut contenir un booléen, une chaine de caractère, une valeur numérique.

Elle peut être initialisée directement:

$ ma_variable=true
$ ma_varaible="Ceci est un texte"
$ ma_variable=45

Une variable peut aussi contenir le résultat d’une commande:

$ ma_variable=$(ls /home)
$ ma_variable=`ls /home`

La 2ème forme est obsolète mais vous pourriez la rencontrer sur des pages web. Nous ne l’utiliserons plus.

Les caractères génériques

Pour de nombreuses commandes (ls, find, grep…) il est nécessaire de connaitre et de taper la totalité du nom du fichier ou de la chaine qu’on recherche.

Mais que se passe-t-il si on ne connait pas précisément le nom du fichier? Ou que l’on recherche un mot précis dans un fichier texte mais son pluriel aussi par exemple (exemple: mot mots).

Il est possible d’utiliser des caractères génériques.

Le caractère générique que tout le monde connaît: *, il remplace n’importe quelle chaine de caractères de n’importe quelle longueur.

Il y a aussi le ? qui remplace n’importe quel caractère unique.

Expansion des variables

Il est possible d’utiliser une variable dans une commande.

Par exemple, je souhaite lister 3 fichiers : toto, titi, tutu. Je peux les stocker dans une variable:

$ fichiers="toto titi tutu"

Pour les lister je pourrai utiliser:

$ ls -l $fichiers

Que se passe-t-il si je place le -l dans la variable?

$ fichiers="-l toto titi tutu"

Est-ce que je peux utiliser la commande suivante pour le même résultat?

$ ls $fichiers

Si mon répertoire contient les 3 fichiers précédents, je peux définir le contenu de la variable à l’aide de la commande:

$ fichiers=$(ls)

Je peux ensuite de nouveau utiliser:

$ ls $fichiers

Que se passe-t-il si un de mes fichiers se nomme tata -l, c’est-à-dire que le nom du fichier contient un espace?

Je peux toujours créer ma variable à l’aide de:

$ fichiers=$(ls)

Que donnera la commande suivante et pourquoi?

$ ls $fichiers

Bash copie la valeur de la variable dans la ligne de commande comme du texte sans se soucier du nombre d’arguments résultant pour la commande.

D’autres pièges doivent être évités avec l’expansion des variables et l’utilisation de guillemets.

Exemple:

La commande find permet de trouver des fichiers (ou des répertoires) dans le système de fichiers. Cette commande prend plusierus paramètres :

  • Un répertoire à partir duquel chercher. La commande cherchera dans ce répertoire et tous ces sous répertoires.

  • Un paramètre de recherche. Il en existe de nombreux mais un des plus couramment utilisé est le nom. En effet, quand on recherche un fichier, on connait souvant son nom. Il est aussi possible de faire des recherche sur d’autres paramètres comme la date de dernière modification, les permisssions…

Structure générale de la commande pour chercher un fichier d’après son nom :

$ find <répertoire> -name <nom>

Un exemple de recherche du fichier nommé services sur tout le disque :

$ find / -name services
Commande Résultat
ls *.txt Affiche tous les fichiers se terminant par .txt
ls “*.txt” Affiche le fichier s’appelant exactement *.txt
find . -name *.txt L’expansion a lieu avant la recherche donc 3 cas sont possibles :
- Si aucun fichier .txt dans le répertoire courant, la commande s’exécutera comme s’il y avait des guillemets.
- S’il y a un fichier .txt dans le répertoire courant, son nom remplacera le *.txt dans la recherche et ce sera donc uniquement ce fichier qui sera recherché.
- S’il y a plusieurs fichiers .txt dans le répertoire, la commande find aura trop d’arguments.
find . -name “*.txt” Recherche tous les fichiers txt à partir du répertoire courant.

Enfin, il existe des syntaxes en bash permettant de factoriser certaines opérations.

Exemple: créer plusieurs fichiers dont un des caractères appartient à une séquence.

On souhaite créer les fichiers patata, patate, patati, patatu

$ touch patat{a,e,i,o,u,y}

On souhaite créer les fichier test1.txt, test2.txt, test3.txttest12.txt:

$ touch test{1..12}.txt

Exercice 1

  1. Créez une variable (variable_etc) contenant la liste des fichiers du répertoire /etc et affichez la.
  • Son contenu est-il facile à lire?

  • Que se passe-t-il si vous exécutez ls suivi du nom de votre variable? Pourquoi?

  1. Sachant que beaucoup de fichiers de configuration se terminent par .conf, trouvez les et stockez leur nom dans une variable.
  • Que se passe-t-il si vous exécutez ls suivi du nom de votre variable?

  • Serez-vous capable d’afficher la taille de chacun des fichiers de configuration?

  1. Créez un répertoire dans lequel vous créerez les fichiers suivants à l’aide de la commande touch en utilisant la syntaxe permettant de factoriser une commande:

test1.txt, test2.txt, test3.txt, test1.doc, test2.doc, test3.doc, test1.tot, test2.tot, test3.tot

Grâce aux caractères génériques, n’affichez que les fichiers txt qui commence par test (plusieurs possibilités existent, essayez de les trouver).

a. Tous les fichiers txt et tot.

b. Tous les fichiers test1

Itération sur le résultat d’une commande

Il existe 2 types de boucle permettant de parcourir le résultat d’une commande:

  • for : mot à mot

  • while : ligne par ligne (vu au prochain cours)

En bash, la syntaxe d’une boucle for est la suivante:

$ for i in arg1 arg2 ...;do commande; done

Exemple :

$ for i in Bienvenus dans le cours Linux; do echo $i; done
Bienvenus
dans
le
cours
Linux

On vient de voir comment parcourir le résultat d’une variable.

On peut stocker le résultat d’une commande dans une variable:

$ texte=$(ls /etc) 
$ for i in $texte; do echo $i; done

Il est aussi possible de passer directement la commande à la boucle for:

$ for i in $(ls /etc); do echo $i; done

ATTENTION à l’expansion des variables dans les boucles for.

Les deux commandes suivantes ne donneront pas le même résultat:

$ for i in *.txt; do echo $i; done

Et

$ for i in "*.txt"; do echo $i; done

Le premier exemple donne une suite de chaine de caractères et chacune sera affichée sur une ligne.

Le deuxième exemple donne une seule chaine de caractères qui sera affichée sur une seule ligne.

Dans un script, on choisira d’écrire la boucle for sur plusieurs ligne en indentant les commandes à l’intérieur de la boucle. On voit bien, dans ce cas, que le do est présent une seule fois.

1for i in $var
2do
3	echo $i
4done
 

Exercices 2

Créez une variable contenant la liste des fichiers du répertoire /bin.

Parcourez cette variable à l’aide d’une boucle for et affichez chacun des fichiers sur une ligne différente.

Sachant qu’il est possible de concaténer les chaines de caractères de cette façon:

$ echo /bin/$i

Essayez d’afficher la taille des fichiers du répertoire /bin.

Exercice 3

Allez deans le répertoire /etc depuis votre répertoire personnel en utilisant un chemin relatif.

Depuis /etc, allez dans le répertoire /etc/skel en utilisant un chemin relatif.

Allez ensuite dans /mnt toujours en utilisant un chemin relatif.

Pour finir, allez dans /usr/bin en utilisant un chemin absolu.