Le shell Bash

Une introduction utilisateur au shell Bash

Bash est (à partir d'aujourd'hui)le de facto shell on most systems you’ll get in touch with: Linux, macOS, and the WSL on Windows 10.

Mise à jour: macOS depuis Catalina (automne 2019) utilise Zsh

Il y a des raisons historiques qui ont fait de Bash la coquille la plus populaire au monde. En 1989, lors de sa première sortie, le monde de la technologie était très différent. À cette époque, la plupart des logiciels du monde UNIX étaient des sources fermées. Unix lui-même était propriétaire et source fermée.

Pour utiliser un système UNIX, vous deviez utiliser un shell.

Le shell le plus populaire à l'époque était une source fermée et propriétaire, il fallait payer pour l'utiliser. C'était la coque Bourne, disponible sous le/bin/shcommander. Il s'appelait «Bourne» parce que son créateur était Steve Bourne.

Richard Stallman dans ces années avec le projet GNU (et plus tard sous Linux) était sur le point de tout révolutionner, en commençant la révolution Open Source. Le projet GNU avait besoin d'un shell et, avec l'aide de la Free Software Foundation, Bash est né. Fortement inspiré du Bourne Shell, Bash signifieCoquille bourne-encoreet c'est un ingrédient clé du projet GNU, et probablement l'un de ses logiciels les plus réussis que nous utilisons encore aujourd'hui.

Bash pourrait exécuter tous les scripts écrits poursh, qui était une fonctionnalité obligatoire pour son adoption, et il a également introduit de nombreuses autres fonctionnalités, depuis les tout premiers jours, offrant une meilleure expérience à ses utilisateurs. Depuis ces premiers jours, Bash a obtenu de nombreuses améliorations. Ce didacticiel décrit les choses les plus populaires et les plus utiles que vous pouvez en faire.

Premiers pas dans Bash

Puisque Bash est le shell par défaut dans de nombreux systèmes, tout ce dont vous avez besoin pour démarrer un shell bash est de

  • connectez-vous au système, s'il s'agit d'un serveur
  • ouvrez votre terminal, s'il s'agit de votre ordinateur

Voir monGuide du terminal macOSpour plus d'informations sur l'utilisation de votre terminal sur un Mac.

Dès que vous le démarrez, vous devriez voir une invite (qui se termine généralement par$).

Comment savez-vous que le shell exécute bash? Essayez de taperhelpet en appuyant sur Entrée.

Voir? Nous venons de dire à Bash d'exécuter lehelpcommander. Cette commande vous montre tour à tour la version de Bash que vous exécutez et une liste de commandes que vous pouvez utiliser.

Attention: voir la version que j'y ai? C'est 3.2.57. Il s'agit de la version Bash par défaut livrée dans macOS, qui n'inclut pas de version supérieure pour les problèmes de licence. Cette version de Bash date de 2014. Installez la dernière version de Bash 5.x en utilisant Homebrew, en tapantbrew install bash.

Le plus souvent, vous n'utiliserez jamais aucune des commandes répertoriées dans l'aide de bash, sauf si vous créezscripts shellou des choses avancées.

99% de l'utilisation quotidienne du shell consiste à naviguer dans des dossiers et à exécuter des programmes tels quels,cdet d'autres utilitaires UNIX communs.

Pour naviguer dans le système de fichiers, vous utiliserez lelscommander. Il est disponible dans le/bin/ls, et puisque Bash a le/bindossier dans sa liste de chemins, vous pouvez simplement taperlspour l'utiliser.

lsrépertorie les fichiers du dossier actuel. Vous commencez généralement à partir de votre dossier de départ, qui dépend du système, mais sur macOS est sous/Users. Mon dossier personnel est dans/Users/flavio. Ce n'est pas lié à Bash, c'est plutôt un système de fichiers UNIX, mais les arguments se chevauchent et si vous n'avez jamais utilisé de shell, il est bon de le savoir.

Pour naviguer vers d'autres dossiers, utilisez lecdcommande, suivie du nom du dossier vers lequel vous souhaitez vous déplacer:

cd Documents

cd ..retourne au dossier parent.

En fonction de votre configuration Bash, vous verrez votre dossier actuel affiché avant l'invite (le$symbole). Ou peut-être pas, mais vous pouvez toujours savoir où vous vous trouvez en tapantpwdet en appuyant sur Entrée.

pwdsignifie * p * nom de * w * orking * d * irectory

Modification de la ligne de commande

Lorsque vous écrivez vos commandes dans le shell, notez que vous pouvez vous déplacer à gauche et à droite avec les touches fléchées. Il s'agit d'une fonctionnalité de shell. Vous pouvez vous déplacer dans vos commandes, appuyer sur le bouton de retour arrière et corriger les commandes. En appuyant sur leenterkey indique au shell d'aller et de laisser le système exécuter la commande.

C'est un comportement normal et accepté, mais quelque chose qui a probablement fait «wow» les premiers utilisateurs d'UNIX.

Les combinaisons de clavier vous permettent d'être rapide lors de l'édition sans atteindre les touches fléchées:

  • ctrl+dpour supprimer le caractère actuellement sélectionné
  • ctrl+faller au personnage de droite
  • ctrl+bpour aller au personnage de gauche

Autocompletion

Une fonctionnalité intéressante de Bash lorsque vous vous déplacez dans le système de fichiers est la saisie semi-automatique. Essayez de tapercd Docet appuyez sur letabclé pour que Bash le remplisse automatiquement pourcd Documents. S'il y a plusieurs choix pour ces premiers caractères, Bash vous renverra la liste, vous pouvez donc taper quelques caractères supplémentaires pour l'aider à supprimer l'ambiguïté et appuyer surtabencore une fois pour terminer.

Le shell peut compléter automatiquement les noms de fichiers, mais aussi les noms de commandes.

Commandes Shell

En utilisant le shell, nous pouvons exécuter les commandes disponibles sur le système. Nous pouvons préfixer les commandes avec le chemin complet (par exemple/bin/lspour lister les fichiers dans un dossier) mais le shell a le concept decheminafin que nous puissions simplement taperlset il sait où se trouvent la plupart des commandes (et nous pouvons ajouter des dossiers à ce chemin en le configurant).

Les commandes acceptent les arguments. Par exemplels /binlistera tous les fichiers dans le/bindossier.

Les paramètres sont précédés d'un tiret-, aimerls -aqui racontelspour afficher également les fichiers cachés. Les fichiers cachés en tant que convention sont des fichiers (et des dossiers) commençant par un point (.).

Commandes shell courantes

Il y a beaucoup de commandes préinstallées sur n'importe quel système, et elles varient considérablement selon qu'il s'agit de Linux / macOS ou même de la distribution Linux que vous utilisez.

Cependant, faisons un bref tour d'horizon des commandes shell les plus courantes que vous pouvez exécuter. Ceux-ci ne sont pas fournis par des shells en soi, mais ce sont plutôt des commandes de ligne de commande que vous pouvez appeler via des shells.

Chaque fois que vous rencontrez des problèmes, comme si vous ne savez pas ce que fait une commande ou que vous ne savez pas comment l'utiliser, utilisezman. Il vous permet d'obtenir de l'aide pour toutes les commandes que je vais lister, et plus encore. Courirman lspar exemple.

Ce sont des commandes de système de fichiers:

  • lspour lister les fichiers
  • cdchanger de dossier
  • rmpour supprimer un fichier ou un dossier
  • mvpour déplacer un fichier vers un autre dossier ou modifier un nom de fichier
  • cppour copier un fichier
  • pwdpour afficher le répertoire de travail actuel
  • mkdirpour créer un dossier

Chaque fichier sur un système de fichiers Unix a des autorisations.chmodvous permet de changer ceux-ci (ne pas y entrer maintenant), etchownvous permet de changer le fichierpropriétaire.

cat,tailetgrepsont deux commandes super utiles pour travailler avec des fichiers.

pico,nano,vimetemacssont des éditeurs couramment installés.

whereissur macOS montre où se trouve une commande sur le système.

Il y a bien sûr beaucoup plus de commandes, mais ce sont quelques-unes que vous pourriez rencontrer plus souvent.

Exécuter des commandes

lsetcdsont des commandes, comme je l'ai mentionné, qui se trouvent dans le/bindossier. Vous pouvez exécuter n'importe quel fichier, du moment qu'il s'agit d'un fichier exécutable, en tapant son chemin complet, par exemple/bin/pwd. Les commandes n'ont pas besoin d'être dans le/bindossier et vous pouvez exécuter les fichiers exécutables qui se trouvent dans votre dossier actuel à./indicateur de chemin.

Par exemple, si vous avez unrunmefichier dans votre/Users/flavio/scriptsdossier, vous pouvez exécuter

cd /Users/flavio/scripts

puis exécutez./runmepour l'exécuter.

Ou tu pourrais courir/Users/flavio/scripts/runmedepuis Bash, où que se trouve votre dossier actuel.

Emplois

Chaque fois que vous exécutez une commande, s'il s'agit d'un programme de longue durée, votre shell appartiendra entièrement à cette commande. Vous pouvez tuer la commande en utilisantctrl-C.

A tout moment, vous pouvez courirjobspour voir les travaux que vous exécutez et leur état.

$ jobs
Job	Group	State	Command
1	72292	stopped	ftp

Another useful command is ps which lists the processes running.

$ ps
  PID TTY           TIME CMD
19808 ttys000    0:00.56 /usr/local/bin/fish -l
65183 ttys001    0:04.34 -fish
72292 ttys001    0:00.01 ftp

top shows the processes and the resources they are consuming on your system.

A job or process can be killed using kill <PID>.

Command history

Pressing the up arrow key will show you the history of the commands you entered. Again, this is a shell feature. Pressing the down arrow key will let you navigate back and forth in time to see what commands you entered previously, and pressing enter will let you run that command again.

This is a quick access to the command history. Running the history command will show you all the commands entered in the shell:

When you start typing a command, Bash can autocomplete it by referencing a previously entered command in the history. Try it by pressing esc followed by tab.

To be honest I find the Fish shell implementation of this to be much better and easier

Setting your default shell

There are many more shells other than Bash. You have Fish, ZSH, TCSH, and others. Any user on the system can choose its own shell.

You set your default login shell by running the chsh -s chsh -s /bin/bash command. You’ll almost never need to do that, unless it was previously changed, for example with Fish:

chsh -s /usr/local/bin/fish

Customizing Bash

I noted before that you might (or might not) see your current working directory in the Bash prompt. Where is this determined? In the Bash configuration!

There’s a bit of confusion here because Bash uses a different configuration file for different scenarios, and it also reads multiple configuration files.

Let’s give some order to this confusion. First, there’s a big distinction whether Bash is initialized as a login shell or not. By login shell we mean that the system is not running a GUI (Graphical User Interface) and you log in to the system through the shell. That’s the case of servers, for example.

In this case, Bash loads this configuration file:

/etc/profile

and then looks in the user home folder and looks for one of these files, in order, executing the first one it finds:

~/.bash_profile
~/.bash_login
~/.profile

were ~ means your home folder (it’s automatically translated by Bash)

This means that if there’s a .bash_profile, ~/.bash_login and ~/.profile are never run, unless explicitly executed in .bash_profile.

If instead of being a login shell Bash is run like I do with macOS, for example, as a normal application, the configuration files change. Bash loads first /etc/bash.bashrc, then ~/.bashrc.

Environment variables

Sometimes you have programs that use environment variables. Those are values that you can set outside of the program, and alter the execution of the program itself. An API key, for example. Or the name of a file.

You can set an environment variable using the syntax

VARIABLE_NAME=variable_value

The value can contain white spaces, by using quotes

VARIABLE_NAME="variable value"

A bash script can use this value by prepending a dollar sign: $VARIABLE_NAME.

Also other programming languages commands can use environment variables, for example here’s how to read environment variables with Node.js.

The system sets up some environment variables for you, like

  • $HOME your home folder
  • $LOGNAME your user name
  • $SHELL the path to your default shell
  • $PATH the path where the shell looks for commands

You can inspect their value by prepending echo to them:

echo $LOGNAME # flavio
echo $HOME # /Users/flavio

A special environment variable: $PATH

I mentioned the $PATH variable. This is a list of folders where the shell will look into when you type a command. Folders are separated by a colon : and they are written in order - Bash will look into the first, search for the command you asked for, and run it if it finds it. Otherwise if goes to the next folder and so on.

My path is currently:

bash-5.0$ echo $PATH
/usr/local/bin:/usr/bin: /bin:/usr/sbin: /sbin:/usr/local/go/bin

You typically edit this in the ~/.bashrc file by prepending or appending items:

PATH = "$PATH:/Users/flavio/bin"

Aliases

Using aliases we can set up shortcuts for common commands. You can give a quick name to a complex combination of parameters, for example.

You define an alias using the syntax

alias <alias>=<command>

if there’s a space in the command you use quotes:

alias <alias>="<command>"

One alias I commonly add to my system is ll:

alias ll="ls --al"

You normally define aliases in your ~/.bashrc file.

Just be careful with quotes if you have variables in the command: using double quotes the variable is resolved at definition time, using single quotes it’s resolved at invokation time. Those 2 are different:

alias lsthis="ls $PWD"
alias lscurrent='ls $PWD'

$PWD refers to the current folder the shell is into. If you now navigate away to a new folder, lscurrent lists the files in the new folder, lsthis still lists the files in the folder you were when you defined the alias.

Advanced command line features

Wildcards

ls and many other commands can make great use of wildcards. You can list all files starting with image:

ls image*

Or all files ending with image:

ls *image

or all files that contain image inside the name:

ls *image*

Redirecting output and standard error error

By default, commands started in the shell print out both the output and errors back to the shell. This might not be what you want. You can decide to write the output to a file instead.

Actually, to a /different file/, because in Unix even the screen is considered to be a file. In particular,

  • 0 identifies the standard input
  • 1 identifies the standard output
  • 2 identifies the standard error

You can redirect the standard output to a file by appending 1> after a command, followed by a file name.

Using the same technique you can use 2> to redirect the standard error.

There is a shortcut > for 1>, since that is used quite a lot.

Example:

ls 1> list.txt 2> error.txt
ls > list.txt 2> error.txt

Another shortcut, &>, redirects /both/ standard output and standard error to a file.

ls &> output.txt

Another frequent thing is to redirect standard error to standard output using 2>&1.

Running a command in the background

You can tell Bash to run a program in the background without it taking control of the shell, by appending & after it:

top &

top is a command that lists the processes running, ordered by most resource consuming.

The application that would normally get control of the shell, is now started but nothing seems to happen. You can bring it back into focus by typing fg (aka *f*ore*g*round), but now we’re entering in the realm of processes and jobs which is a big topic on its own, but a quick overview:

When a command is running you can use ctrl-Z to pause it and bring it to the background. The shell comes back again in the foreground, and you can now run bg to move resume execution of that previously paused job.

When you are ready to go back to it, run fg to bring back that program in the foreground.

You can see all processes running using ps, and the list shows all the processes pid numbers. Using the paused process pid, you can bring to foreground a specific command, for example fg 72292. Same works for bg.

Queuing commands

You can instruct Bash to run a command right after another ends by separating them with a semicolon:

cd /bin; ls

You can repeat this to queue multiple commands in the same line.

Output redirection

A program can receive input from any file using the < operator, and save to a file the output using the > operator:

echo hello > result.txt
wc < result.txt

wc is a command that counts the words it receives as input.

Pipe

Using pipes, any command output can be used as input for a second command. Use the | operator to combine the two. In this example, wc gets its input from the output of echo hello:

echo hello | wc

Grouping commands

Use && to combine two commands using “and”. If the first command executes without problems, run the second, and so on.

Use || to combine two commands using “or”. If the first command executes without problems the second does not run.

! negates the next logical operation:

$ echo hello && echo test
hello
test
$ echo hello || echo test
hello
$ ! echo hello || echo test
hello
test

You can use parentheses to combine expressions to avoid confusion, and also to change the precedence:

$ ! (echo hello) || (echo test)
hello
test
$ ! (echo hello || echo test)
hello

Programming shells

One of the best features of a shell like Bash is its ability to create programs with it, by basically automating commands execution.

I’m going to write a separate guide on Bash scripting soon, which will be separate from this tutorial because the topic is really more in-depth than what I want to add in this introductory Bash guide.

A quick intro though: a script is a text file that starts with a line that indicates that it’s a shell script (and what shell it requires), followed by a list of commands, one per line. Example:

#!/bin/bash
ls

You can save this as a file myscript and make it executable using chmod +x myscript, and run it using ./myscript (./ means “current folder”).

Shell scripting is outside of the scope of this post, but I want you to know about this. Scripts can have control structures and many other cool things.

This same scripting strategy works for other shells, like Zsh:

#!/bin/zsh
ls

Download my free Linux Commands Handbook


More cli tutorials: