12.1. Les commandes basiques

Les commandes incontournables pour le débutant

ls

La commande élémentaire de << listage >> du contenu d'un répertoire. Il est très facile d'en sous-estimer la puissance. Par exemple, en utilisant -R, option de récursivité, ls affiche une structure de répertoire sous la forme d'une arborescence. D'autres options dignes d'intêret sont -S, qui trie selon la taille du fichier, -t, qui trie selon la date de modification des fichiers, et -i, qui affiche les inodes des fichiers (voir Exemple 12-3).

Exemple 12-1. Utilisation de ls pour créer une liste de fichiers à graver sur un CDR

#!/bin/bash
# burn-cd.sh
# Script d'automatisation de gravure de CD.


SPEED=2          # Peut être plus élevée si votre graveur en est capable.
IMAGEFILE=cdimage.iso
CONTENTSFILE=contents
DEFAULTDIR=/opt  # C'est le repertoire contenant les fichiers à graver.
                 # Soyez sûr qu'il existe bien.

# Utilise le package "cdrecord" de Joerg Schilling.
# (http://www.fokus.gmd.de/nthp/employees/schilling/cdrecord.html)

#  Si ce script est lancé par un utilisateur normal, alors il faut faire un suid sur cdrecord
#+ (chmod u+s /usr/bin/cdrecord, en tant que root).

if [ -z "$1" ]
then
  IMAGE_DIRECTORY=$DEFAULTDIR
  # Le répertoire par défaut, si non défini par la ligne de commande.
else
    IMAGE_DIRECTORY=$1
fi

# Créer un fichier "sommaire".
ls -lRF $IMAGE_DIRECTORY > $IMAGE_DIRECTORY/$CONTENTSFILE
# L'option "l" donne un "long" listing de fichier.
# L'option "R" rend le listing récursif.
# L'option "F" marque le type des fichiers (les répertoires se voient ajouter un / final).
echo "Sommaire en cours de création."

# Créer un fichier image avant de le graver sur CD.
mkisofs -r -o $IMAGFILE $IMAGE_DIRECTORY
echo "Image ISO9660 ($IMAGEFILE) en cours de création."

# Grave le CD.
cdrecord -v -isosize speed=$SPEED dev=0,0 $IMAGEFILE
echo "Gravure du CD."
echo "Veuillez patientez."

exit 0
cat, tac

cat, un acronyme de concatenate (NdT: concaténer en français), affiche le contenu d'un fichier sur stdout. Lorsqu'il est combiné avec une redirection (> ou >>), il est couramment utilisé pour concaténer des fichiers.
cat nom_fichier cat fichier.1 fichier.2 fichier.3 > fichier.123
L'option -n de cat insère, avant chaque début de ligne, un numéro de ligne dans le(s) fichier(s) cible(s). L'option -b sert à numéroter uniquement les lignes qui ne sont pas blanches. L'option -v montre les caractères non imprimables en utilisant la notation ^. L'option -s n'affiche qu'une seule ligne blanche lors de multiples lignes blanches consécutives.

Voir aussi Exemple 12-21 et Exemple 12-17.

tac, le contraire de cat, affiche le contenu d'un fichier en commençant par sa fin.

rev

Inverse chaque ligne d'un fichier et affiche le résultat vers stdout. Le résultat est différent d'une utilisation de tac, dans le sens où rev conserve l'ordre des lignes, mais << retourne >> chacune d'elle.

bash$ cat fichier1.txt
Coucou, je suis la ligne 1.
Coucou, je suis la ligne 2.


bash$ tac fichier1.txt
Coucou, je suis la ligne 2.
Coucou, je suis la ligne 1.


bash$ rev fichier1.txt
.1 engil al sius ej ,uocuoC
.2 engil al sius ej ,uocuoC 
	      

cp

Il s'agit de la commande de copie de fichier. cp fichier1 fichier2 copie fichier1 dans fichier2 et écrase fichier2 s'il existait auparavant (voir Exemple 12-5).

Astuce

Les options -a, pour option d'archive (pour copier une arborescence entière de répertoire), -r et -R pour option de récursivité sont particulièrement utiles.

mv

Il s'agit de la commande de déplacement (move). Elle est équivalente à une combinaison des commandes cp et rm. Elle peut être utilisée pour déplacer plusieurs fichiers vers un répertoire ou même pour renommer un répertoire. Pour des exemples d'utilisation dans un script, voir Exemple 9-17 et Exemple A-3.

Note

Lors de l'utilisation de mv dans un script, on doit ajouter l'option -f (forcer) pour empêcher toute interaction avec l'utilisateur.

Quand un répertoire est déplacé vers un répertoire déjà existant, il devient un sous-répertoire du répertoire existant.

bash$ mv rep_source rep_cible

bash$ ls -lF rep_cible
total 1
 drwxrwxr-x    2 bozo  bozo      1024 nov 21 23:30 rep_source/
	      

rm

Efface, supprime (<< remove >> en anglais) un ou plusieurs fichiers. L'option -f force même la suppression de fichiers en lecture seule et est utile pour ignorer toute interaction de l'utilisateur durant son exécution dans un script.

Avertissement

Lorsqu'elle est exécutée avec l'option de récursivité (NdT: en anglais, << recursive flag >>) -r, cette commande efface les fichiers de tous les sous-répertoires de l'arborescence.

rmdir

Efface un répertoire (<< remove directory >> en anglais). Il est nécessaire que le répertoire soit vide de tout fichier, ce qui inclut les fichiers invisibles (NdT: en anglais, les << dotfiles >>), [1] pour que cette commande s'exécute correctemment.

mkdir

Crée un répertoire (NdT: << make directory >> en anglais). mkdir -p projet/programmes/Decembre crée le répertoire indiqué. L'option -p s'occupe, au besoin, de la création des répertoires parents automatiquement.

chmod

Change les attributs d'un fichier existant (voir Exemple 11-10).

chmod +x nom_fichier
# Rend "nom_fichier" exécutable pour tous les utilisateurs.

chmod u+s nom_fichier
# Active le bit de permission "suid" de "nom_fichier".
#  Un utilisateur ordinaire peut exécuter "nom_fichier" avec les mêmes
#+ permissions que son propriétaire.
# (Ceci ne s'applique pas aux scripts shell.)

chmod 644 nom_fichier
#  Active les permissions de lecture/écriture de "nom_fichier" pour son
#+ propriétaire et lecture seulement pour
# les autres (mode octal).

chmod 1777 nom_rep
#  Donne à tout le monde les permissions de lecture, d'écriture et d'exécution
#+ dans le répertoire mais active aussi le "sticky bit".
#  Cela signifie que seul le propriétaire du répertoire, le propriétaire du
#+ fichier et, bien sûr, root peuvent effacer n'importe quel fichier de ce
#+ répertoire.

chattr

Change les attributs de fichier (NdT: << change file attributes >> en anglais). Elle agit de la même manière que chmod mais avec une syntaxe d'invocation différente et ne fonctionne que sur les systèmes de fichiers ext2.

ln

Crée des liens vers des fichiers déjà existants. Cette commande est utilisée la plupart du temps avec l'option -s, pour lien symbolique ou << soft >>. Cela permet de référencer le fichier lié par plus d'un nom et est une alternative supérieure au système d'alias (voir Exemple 4-6).

ln -s ancien_fichier nouveau_fichier lie le fichier ancien_fichier au lien nouvellement créé, nouveau_fichier.

man, info

Ces commandes accèdent aux pages de manuel et d'information relatives aux commandes systèmes et autres utilitaires installés sur la machine. Les pages info, si disponibles, contiennent habituellement des descriptions bien plus détaillées que celles des pages man.

Notes

[1]

Il s'agit de fichiers dont le nom commence par un point, par exemple ~/.Xdefaults. De tels noms de fichiers ne sont pas affichés lors d'un ls, et ne risquent donc pas d'être effacés accidententellement par une commande rm -rf *. Ces fichiers sont utilisés habituellement en tant que fichiers de configuration situés dans le répertoire principal d'un utilisateur.

>Attention

Le paquet widtools (widget tools, outils pour objets) nécessite que la bibliothèque XForms soit installée. De plus, le Makefile a besoin d'être édité de façon judicieuse avant que le paquet ne soit construit sur un système Linux typique. Finalement, trois des six objets offerts ne fonctionnent pas (en fait, ils génèrent un défaut de segmentation).

Pour plus d'efficacité des scripts utilisant des widgets, essayez Tk ou wish (des dérivés de Tcl), PerlTk (Perl avec des extensions Tk), tksh (ksh avec des extensions Tk), XForms4Perl (Perl avec des extensions XForms), Gtk-Perl (Perl avec des extensions Gtk), ou PyQt (Python avec des extensions Qt).

do # Q[n] = Q[n - Q[n-1]] + Q[n - Q[n-2]] for n>2 # Nécessaire de casser l'expression en des termes intermédiaires. # car Bash ne gère pas très bien l'arithmétique des tableaux complexes. let "n1 = $n - 1" # n-1 let "n2 = $n - 2" # n-2 t0=`expr $n - ${Q[n1]}` # n - Q[n-1] t1=`expr $n - ${Q[n2]}` # n - Q[n-2] T0=${Q[t0]} # Q[n - Q[n-1]] T1=${Q[t1]} # Q[n - Q[n-2]] Q[n]=`expr $T0 + $T1` # Q[n - Q[n-1]] + Q[n - ![n-2]] echo -n "${Q[n]} " if [ `expr $n % $LONGUEURLIGNE` -eq 0 ] # Formatte la sortie. then # mod echo # Retour chariot pour des ensembles plus jolis. fi done echo exit 0 # C'est une implémentation itérative la Q-series. # L'implémentation récursive plus intuitive est laissée comme exercice. # Attention: calculer cette série récursivement prend *beaucoup* de temps.

--

Bash supporte uniquement les tableaux à une dimension, néanmoins une petite astuce permet de simuler des tableaux à plusieurs dimensions.

Exemple 26-9. Simuler un tableau à deux dimensions, puis son test

#!/bin/bash
# Simuler un tableau à deux dimensions.

# Un tableau à deux dimensions stocke les lignes séquentiellement.

Lignes=5
Colonnes=5

declare -a alpha     # char alpha [Lignes] [Colonnes];
                     # Déclaration inutile.

charge_alpha ()
{
local rc=0
local index


for i in A B C D E F G H I J K L M N O P Q R S T U V W X Y
do
  local ligne=`expr $rc / $Colonnes`
  local colonne=`expr $rc % $Lignes`
  let "index = $ligne * $Lignes + $colonne"
  alpha[$index]=$i   # alpha[$ligne][$colonne]
  let "rc += 1"
done  

# Un peu plus simple
#   declare -a alpha=( A B C D E F G H I J K L M N O P Q R S T U V W X Y )
# mais il manque néanmoins le "bon goût" d'un tableau à deux dimensions.
}

affiche_alpha ()
{
local ligne=0
local index

echo

while [ "$ligne" -lt "$Lignes" ]  # Affiche dans l'ordre des lignes -
do                                # les colonnes varient
                                  # tant que ligne (la boucle externe) reste
				  # identique
  local colonne=0
  
  while [ "$colonne" -lt "$Colonnes" ]
  do
    let "index = $ligne * $Lignes + $colonne"
    echo -n "${alpha[index]} "  # alpha[$ligne][$colonne]
    let "colonne += 1"
  done

  let "ligne += 1"
  echo

done  

# Un équivalent plus simple serait
#   echo ${alpha[*]} | xargs -n $Colonnes

echo
}

filtrer ()     # Filtrer les index négatifs du tableau.
{

echo -n "  "

if [[ "$1" -ge 0 &&  "$1" -lt "$Lignes" && "$2" -ge 0 && "$2" -lt "$Colonnes" ]]
then
    let "index = $1 * $Lignes + $2"
    # Maintenan, l'affiche après rotation.
    echo -n " ${alpha[index]}"  # alpha[$ligne][$colonne]
fi    

}
  



rotate ()  # Bascule le tableau de 45 degrés
{          # (le "balance" sur le côté gauche en bas).
local ligne
local colonne

for (( ligne = Lignes; ligne > -Lignes; ligne-- ))  # Traverse le tableau en
#	sens inverse.
do

  for (( colonne = 0; colonne < Colonnes; colonne++ ))
  do

    if [ "$ligne" -ge 0 ]
    then
      let "t1 = $colonne - $ligne"
      let "t2 = $colonne"
    else
      let "t1 = $colonne"
      let "t2 = $colonne + $ligne"
    fi  

    filtrer $t1 $t2   # Filtre les index négatifs du tableau.
  done

  echo; echo

done 

# Rotation du tableau inspirée par les exemples (pp. 143-146) de
# "Advanced C Programming on the IBM PC", par Herbert Mayer
# (voir bibliographie).

}


#-----------------------------------------------------#
charge_alpha     # Charge le tableau.
affiche_alpha    # L'affiche.
rotate           # Le fait basculer sur 45 degrés dans le sens contraire des
                 # aiguilles d'une montre.
#-----------------------------------------------------#


# C'est une simulation assez peu satisfaisante.
#
# Exercices:
# ---------
# 1)  Réécrire le chargement du tableau et les fonctions d'affichage
#   + d'une façon plus intuitive et élégante.
#
# 2)  Comprendre comment les fonctions de rotation fonctionnent.
#     Astuce: pensez aux implications de l'indexage arrière du tableau.

exit 0

Un tableau à deux dimensions est essentiellement équivalent à un tableau à une seule dimension mais avec des modes d'adressage supplémentaires pour les références et les manipulations d'éléments individuels par la position de la << ligne >> et de la << colonne >>.

Pour un exemple encore plus élaboré de simulation d'un tableau à deux dimensions, voir Exemple A-11.