Gestion des fichiers sous Unix/Linux

Organisation logique des fichiers

Nous allons découvrir l'organisation des fichiers sous Unix

Démarrer Linux Ubuntu sur un poste de la salle Gif 10

Dans Applications ouvrir un Terminal

Entrer firefox puis faire Entrée, puis aller sur mathly récupérer le Tp

Le système de gestion de fichiers d'Unix (ou de Linux), structure la mémoire du disque dur (attention ! ce n'est pas la mémoire vive) sous la forme d'un arbre dont les noeuds sont soit des répertoires soit des fichiers

Un répertoire peut contenir d'autres répertoires ou des fichiers

Voici la disposition des répertoires pour le système Linux (Ubuntu)

Quand on ouvre un terminal on se trouve dans le répertoire du nom de l'utilisateur avec lequel on s'est connecté à la machine

Ce répertoire matérialisé par le symbole tilde ~ est plus précisement dans la structure hiérarchique de l'organisation des fichiers /home/nom_utilisateur

/ (lire slash) est la racine de l'arbre dont les enfants sont les répertoires visibles sur la copie d'écran ci-dessus

Entrez la commande pwd (pour print working directory) pour l'observer sur votre machine

Sur la copie d'écran ci-dessous l'utilisateur s'appelle jp "chez" l'ordinateur appelé vhjp (c'est le sens de jp@vhjp) et le répertoire courant est /home/jp

Unix/Linux est un système multi-utilisateurs donc plusieurs utilisateurs peuvent utiliser le même ordinateur, chaque utilisateur a son répertoire dans le répertoire home

Dans le répertoire de chaque utilisateur on trouve au moins les répertoires Documents, Images et Téléchargements

Entrez dans le terminal la commande


ls -R

(pour list)Cette commande va lister le contenu du répertoire de l'utilisateur de manière récursive (c'est le rôle de l'option -R), ainsi dans le terminal tout l'arbre de l'utilisateur va être affiché de manière récursive et on verra affiché le contenu des sous-répertoires de jp, ainsi par exemple le sous-répertoire ./Documents: puis en colonne le contenu du sous-répertoire Documents de jp

Le symbole ./ signifie le répertoire courant (On reverra cela plus loin)

Il nous faut préciser ici la notion de chemin absolu et de chemin relatif

Pour bien comprendre ces notions le mieux est de pratiquer avec un fichier ex.html et une image chat.png

Télécharger le fichier ex.txt puis enregistrer le sous ex.html dans Documents

Télécharger chat.png dans Documents

Le but de la manipulation est qu'au lancement de la page ex.html par le navigateur, l'image chat.png soit affichée

Ceci n'est possible que si dans la balise img le paramètre src (pour source) est correctement renseigné, par l'adresse absolue ou relative de l'image par rapport à ex.html

Un fichier ou un répertoire est repéré absolument par rapport à la racine /, ainsi le répertoire jp dans l'exemple ci-dessus a pour chemin absolu

/home/jp

Comment le fichier html va trouver l'image ?

  1. on donne l'adresse absolue de l'image, c'est à dire

    /home/jp/Documents/img.png

    Ce qui est un peu long !

  2. On donne l'adresse relative de l'image, ici c'est simple car on travaille souvent ainsi en mettant les fichiers dans le même répertoire autrement dit l'adresse relative est img.png

    On peut aussi écrire src="./chat.png", ./ signifiant aller chercher l'image dans le répertoire courant où est exécuté le programme, ici Documents

Exercices

On va maintenant déplacer l'image non pas en utilisant les outils graphiques mais avec les commandes du terminal

Entrez dans le terminal (on suppose que vous êtes dans votre répertoire personnel à votre nom qui ne s'appelle évidemment pas jp, il faut adapter ...)


mv Documents/chat.png Images/chat.png

La commande mv pour move déplace l'image à partir de son adresse relative Documents/chat.png vers sa nouvelle adresse relative Images/chat.png

Pour vérifier que l'image est bien déplacée vous pouvez soit le faire graphiquement soit entrez dans le terminal


cd Images

cd signifie change directory et vous permet de vous déplacer dans l'arbre et quitter votre répertoire et "descendre " d'un niveau et d'aller dans le répertoire Images

Pour remonter d'un niveau dans l'arbre peu importe où on se trouve on entre la commande suivante


cd ..

Les deux points .. représentent le répertoire père de celui où vous êtes

Maintenant pour voir le contenu du répertoire Images et constater que l'image s'y trouve bien entrez la commande


ls

Maintenant vous en savez assez pour pratiquer par vous-même

  1. Il faut changer le contenu de src sinon la page ex.html n'affichera pas l'image

    Pour passer de ex.html qui est dans Documents à chat.png qui est maintenant dans Images on doit remonter dans le répertoire "père" puis descendre dans Images

    Donc src="../Images/chat.png"

    Essayez

  2. Dans le répertoire Documents on va créer un nouveau répertoire nommé html

    On se déplace d'abord dans le répertoire Documents,(à vous de jouer) si vous ne savez plus où vous êtes faites pwd

    Une fois que vous êtes dans bien dans Documents entrez dans le terminal

    
    mkdir html
    
    

    mkdir pour make directory va créer le répertoire dont le nom suit la commande, et donc html est un répertoire enfant de Documents

  3. Fermer le navigateur et déplacer le fichier ex.html dans le répertoire html puis ouvrir ex.html avec le navigateur

    Vous observez que l'image ne s'affiche plus et donc il faut mettre à jour l'attribut src dans le fichier ex.html

Droits des fichiers

A chaque fichier sont associés des droits

Puisque plusieurs personnes peuvent utiliser la même machine, à chaque fichier créé sont associés un certain nombre de droits

Placer vous dans votre répertoire Documents puis entrer la commande suivante

    
        ls -l
    

Vous pouvez voir sur chaque ligne en plus du nom du fichier ou du répertoire une suite de lettres séparées en trois groupes

  1. Le premier groupe concerne l'utilisateur c'est à dire le créateur du fichier
  2. Le deuxième groupe concerne le groupe principal dans lequel se trouve le créateur du fichier
  3. Le troisième groupe concerne les autres utilistaurs de la machine

Exercices

  1. Créer un fichier texte vide fichier.txt avec la commande suivante
        
            touch fichier.txt
        
    
  2. On veut donner aux autres membres de l'équipe du propriétaire le droit à l'écriture sur ce fichier Entrez la commande suivante
        
            chmod g+w fichier.txt
        
    
  3. Avec quelle commande vérifier que la modification a été bien faite ?

Scripts bash (Première partie)

Le droit d'exécution qui permet de rendre un fichier exécutable et de pouvoir éventuellement réaliser des actions potentiellement dangereuses pour l'intégrité de la machine est plus encadré que les autres modes. Nous allons découvrir cela sur un exemple

  1. Entrer dans un terminal la commande nano& pour ouvrir un éditeur de textes directement dans le terminal. Cet éditeur de textes est moins sophistiqué que gedit (on ne peut pas utiliser la souris) mais il suffira pour écrire des programmes bash

    Ensuite entrer les lignes de code suivantes

        
    #!/bin/bash 
    
    # ce programme affiche dans le Terminal
    # la phrase Programmation en bash
    
    echo "Programmation en bash"
    
    

    Ensuite faire CTRL+X pour quitter, confirmer l'enregistrement en choisissant O puis nommer votre programme test.sh

  2. Observer que votre fichier test.sh n'a pas de droits d'exécution

    Donner les droits d'exécution à user pour test.sh

  3. Pour exécuter le script entrer la commande suivante
        
            ./test.sh
        
    

    Explication: Il existe une variable d'environnement PATH contenant tous les répertoires contenant des exécutables comme /bin ,/usr/bin etc... aussi pour lancer un exécutable il y a deux solutions

    • Soit c'est un exécutable faisant partie d'une catégorie d'exécutables bien répertoriés dans le PATH comme les applications courantes comme un navigateur etc... dans ce cas il suffit d'entrer le nom de l'application et faire entrée, par xemple pour firefox, gedit etc..
    • Si c'est un script bash et vous n'en faites pas souvent dans ce cas il faut entrer l'adresse absolue du script autrement dit dans notre cas

          
              /home/nsi/test.sh
          
      

      qu'il est plus court d'écrire

          
              ./test.sh
          
      

      . signifiant le répertoire courant

    • On aurait pu aussi écrire

          
          ~/test.sh
          
      
    • Si ~ est dans le PATH dans ce cas on aurait pu faire

          
          test.sh
          
      
    • Afficher le contenu de la variable PATH dans le terminal en faisant
          
          echo $PATH
          
      
  4. Maintenant on va découvrir les variables, une variable a un nom nom_var et un contenu $nom_var

    Ecrire dans test.sh, sauvegarder et exécuter

        
    #!/bin/bash 
    
    # une variable a un nom nom_var
    # et un contenu $nom_var
    
    x="Nous sommes le "
    y=12
    z=" avril "
    t=2020
    echo $x $y $z $t
    
    
  5. Que se passe-t-il si on écrit echo x y z t?
  6. On aimerait récupérer le résultat d'une commande shell comme ls dans le contenu d'une variable

    Ceci est possible avec la commande $()

        
    #!/bin/bash 
    
    # On liste le répertoire courant ./
    
    
    echo $(ls ./)
    
    
  7. Quelle est la différence avec écrire ls ./ au lieu de $(ls ./) ?
  8. Ecrire le code suivant puis l'exécuter

        
    #!/bin/bash 
    
    # On mémorise le contenu du répertoire courant ./
    # puis on l'affiche 
    
    contenu=$(ls ./)
    echo $contenu
    
    
  9. Est il possible d'écrire contenu=ls ./ ?
  10. Exercice

    • La commande cat permet d'afficher dans un terminal le contenu d'un fichier texte. Essayez la (voir le manuel en utilisant la commande man)
    • Ecrire un script qui une fois exécuté affiche son code dans le terminal
  11. Un script bash peut avoir des arguments comme une fonction en Python

    La commande shell wc permet d'obtenir des informations sur un fichier par xemple le nombre d'octets ou encore le nombre de mots ou de caractères si c'est un fichier texte (voir le manuel)

    Le script suivant affiche le nombre de mots contenus dans un fichier texte

        
        #!/bin/bash 
    
    # $1 est le premier argument du script , ici un fichier texte
    # $2 le deuxième etc...
    
    wc -w $1
    
    

    Il faut cependant créer un fichier texte soit avec nano ou alors insérer la phrase "Nous sommes le 12 avril 2022" dans un fichier texte exemple.txt

    Entrer dans un terminal

        
    $echo "Nous sommes le 12 avril 2022" > exemple.txt
    
    

    Puis entrer dans le terminal

        
    $./test.sh exemple.txt
    
    

Scripts bash (Deuxième partie)

Nous allons découvrir les tests
  1. Nous allons faire un script qui en fonction de l'argument passé en paramètre affiche dans le terminal si c'est un fichier ou un répertoire

        
    #!/bin/bash 
    
    if [ -d $1 ] 
    then 
       echo "$1 est un répertoire"
    fi
    if [ -f $1 ] 
    then 
       echo "$1 est un fichier"
    fi
    
    
  2. Pour faire des tests mettant en jeu des expressions arithmétiques évaluables on procède ainsi

        
    #!/bin/bash 
    # $1 est nombre passé en paramètre
    if (($1 > 0))
    then 
       echo "$1 est un nombre positif"
    else
    then
       echo "$1 est négatif ou nul"
    fi
    
    
  3. Exercice

    • Faire un script max.sh prenant deux nombres en paramètres et affichant dans le terminal le plus grand des deux nombres
    • Faire un script delta.sh prenant trois nombres a,b et c en paramètres et affichant dans le terminal si l'équation $ax^2+bx+c = 0$ a deux solutions, une ou aucune

Scripts bash (Troisième partie)

Nous allons découvrir la boucle for et la boucle while
  1. Nous allons faire un script qui liste le contenu d'un répertoire dans une variable puis parcourt cette variable à l'aide d'une boucle for puis pour chaque élément si c'est un fichier texte compte le nombre de mots du fichier texte

        
        #!/bin/bash  
        #$1 est le contenu du répertoire passé en paramètre
        liste_fichiers=$(ls $1) 
        for fichier in $liste_fichiers
        do 
              #le script est exécuté dans ~, l'adresse relative est $1/$fichier
              if [ -f $fichier ] 
              then
                 wc -w $1/$fichier
              fi
        done
    
    
  2. Nous allons faire un script qui calcule la somme de tous les nombres entrés en paramètre et affiche le résultat dans le terminal

    $* est la liste de tous les paramètres

        
        #!/bin/bash  
        #$* est la liste de tous les nombres 
        #passés en paramètre 
        somme=0 
        for nombre in $*
        do 
           ((somme=$somme + $nombre))     
        done
        echo "la somme vaut" $somme
    
    
  3. Nous allons faire un script pour la suite 3n + 1

        
        #!/bin/bash  
        #$1 est un entier
        n=$1
        while (($n != 1))
        do
          if (($n >> 1 << 1 == $n))
          then 
             ((n = $n >> 1))
          else
             ((n = 3*$n + 1))
           fi
           echo $n 
        done 
    
    
  4. Exercice

    • Modifier le script précédent de telle sorte que sera affiché l'élément le plus grand rencontré et le nombre total d'éléments
    • Faire un script qui liste un répertoire et qui regarde si un certain type de fichier s'y trouve comme des captures d'écran inutilisées par exemple et dans ce cas les déplace dans une corbeille (un répertoire créé pour l'occasion)

Traitement automatisé de fichiers

L'intérêt de faire des scripts shell est surtout de pouvoir automatiser la gestion des fichiers et des répertoires de son ordinateur

Par exemple de nombreux programmes Python peuvent être "éparpillés" à différents endroits et il serait intéressant de programmer un rangement "automatique" de ces fichiers dans un répertoire dédié

  1. Créer un répertoire Python, enfant du répertoire ~
  2. On va créer des fichiers .py "fictifs", une dizaine dans le ~, une dizaine dans Téléchargements, puis une dizaine dans Documents

    Pour cela on va utiliser le script suivant, appelé cree_fichier.sh

        
        #!/bin/bash  
        #$1 est l'adresse absolue du répertoire passé en paramètre 
        # on se met dans $1
        cd $1
    
        #on créé 10 fichiers vides .py
        for ((i=0;i < 10;i++))
        do 
           touch prgm_$i.py    
        done
    
    
  3. Exécuter le script précédent et vérifier la création des fichiers .py
  4. Le caractère * se substitue à n'importe quelle chaîne de caractères ainsi *.py signifie tout fichier se terminant par .py

    Dans ~ entrer la commande suivante

        
       echo *.py
    
    

    Observer l'affichage dans la console de tous les fichiers créés précédemment dans ~

    Aller dans un répertoire où il n'y a pas à priori de fichier .py, comme Images et exécuter la commande précédente, vous observerez que dans le terminal s'affiche non pas rien mais *.py

  5. On doit donc être capable de comparer des chaines de caractères en shell

        
       x='ab';y='Ab';z='ab' 
    
    

    Puis entrer dans le terminal

        
       [ $x = $y ];echo $?
    
    

    Vous obtenez 1 qui ici signifie Faux

    Puis entrer dans le terminal

        
       [ $x = $z ];echo $?
    
    

    Vous obtenez 0 qui ici signifie Vrai

  6. Compléter le script python.sh qui prend un répertoire (adresse absolue) affiche tous les fichiers (éventuels) .py contenus dans ce répertoire et les déplace dans le répertoire Python

        
        #!/bin/bash  
        #$1 est l'adresse absolue du répertoire passé en paramètre 
        cd $1
        # on fait afficher tous les fichiers .py 
        # se trouvant dans $1 et on récupère
        # ces fichiers dans une variable liste_fichiers 
        
        liste_fichiers=$(echo *.py)
        
        if [.............]
        then
           echo "pas de fichier .py"
        else
           for fichier in $liste_fichiers
           do 
                ...............    
           done
           echo "fin de traitement"
        fi 
    
    
  7. Exécutez le script précédent sur ~, Documents et Téléchargements et observez que les fichiers Python sont correctement rangés

Utilisation de cron (chrono table) pour automatiser un script en fonction d'une date

cron est un programme qui tourne en arrière-plan et qui peut lancer un script shell à une certaine heure ou/et à certaines fréquences

Par exemple on peut vouloir ranger les fichiers Python une fois par mois ou une fois par an

  1. Afficher le manuel pour cron
  2. Afficher les fichiers /usr/lib/cron/cron/cron.allow et /usr/lib/cron/cron/cron.deny
  3. Entrer dans le terminal la commande suivante pour remplir votre crontab avec l'éditeur de texte nano

        
       export VISUAL=nano;crontab -e
    
    

    On va lancer python.sh 5 minutes après avoir rempli crontab

    Imaginons qu'il est 9h 30 le 19 avril 2022 qui est un mardi, deuxième jour de la semaine, on va donc demander à cron de lancer python.sh sur ~ à 9h 35

    On redirige l'exécution vers un journal au cas où il y a eu un problème

        
       #minutes(0-59) heures(0-23) jour du mois(1-31) mois(1-12) jour_semaine(1-7)
       35 09 19 04 2 ~/python.sh ~>>~/rangement_python.log 
    
    

    Si on veut lancer le script tous les premiers du mois à 12h 00

        
       00 12 1 * * ~/python.sh ~>>~/rangement_python.log 
    
    
  4. Sauvegardez votre crontab puis attendez et observez

Traitement de données en tables avec le bash

Un fichier .csv (comma separated values) permet de stocker des données nombreuses avec une taille "raisonnable"

On peut le considérer comme un ensemble de lignes et de colonnes sur lequel on peut faire des recherches

On va par exemple travailler sur un fichier (anonymisé) contenant les choix de spécialité des élèves de première du LVC de l'année 2019 -2020 pour l'année suivante 2020-2021

  1. On va télécharger un fichier .csv du site mathly.fr avec la commande wget,mais comme au Lycée on a accès au réseau Internet via un proxy, on utilise l'option -e avec paramètres use_proxy=on et http_proxy=10.0.0.1:3128

    
    wget -e use_proxy=on -e http_proxy=10.0.0.1:3128 http://www.mathly.fr/terminale_20_21.csv 
    
    
    

    Le fichier terminale_20_21.csv est enregistré dans le répertoire courant

    Pour macos sans proxy faire

    
    curl http://mathly.fr/terminale_20_21.csv >> terminale_20_21.csv
    
    

    Pour afficher la première ligne du fichier terminale_20_21.csv (métadonnées)

    On entre la commande

                    
    head -n1 terminale_20_21.csv
    
    
  2. On veut sélectionner les lignes du fichier terminale_20_21.csv contenant le motif 'Numérique et Sciences Informatiques'

                    
        grep 'Numérique et sciences informatiques' terminale_20_21.csv
    
    
  3. Voici la première ligne du fichier

    Spécialités suivies en Première;Spécialités suivies en Terminale; Spécialité NON POURSUIVIE en Terminale;Options débutées en Terminale

    On veut sélectionner la colonne du fichier terminale_20_21.csv contenant les spécialités suivies en Terminale (deuxième colonne)

    Il faut sélectionner le champ numéro 2 (field) avec le délimiteur (;)

    
    cut -d';' -f2 terminale_20_21.csv
    
    

    Le résultat de cette commande est affichée dans le terminal

    On aimerait conserver le résultat dans un fichier spe_terminale.txt

    On va rediriger la sortie non pas vers le terminal mais vers le fichier spe_terminale.txt

        
    cut -d';' -f2 terminale_20_21.csv>spe_terminale.txt 
    
    
  4. Quelle commande entrer pour sélectionner dans le fichier spe_terminale.txt uniquement les lignes contenant Numérique et sciences informatiques?
  5. Quelle commande entrer pour compter le nombre d'élèves qui font la spécialité Numérique et sciences informatiques en Terminale?