1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
|
% The Linux command-line
---
subtitle: WTF is Linux
---
[back](index.md)
## Purpose
The main purpose of the command line is to execute other programs using a text
only interface.
While "program" in a broader context might imply a user interface with
a separate window, buttons, etc., what I mean here is a program that only
outputs text for us to see.
While the command-line was mostly created because historically, computers
weren't quite powerful[^teletypewriter], it's still used to this day by a large
amount of people for various reasons (some people find it handy, clearer,
faster, or even more elegant).
[^teletypewriter]:
It's also likely that it was created is because computers didn't even have
screens before, but instead [printed text on paper](https://en.wikipedia.org/wiki/Teleprinter).
[Example](https://spacepub.space/videos/watch/d8943b2d-8280-497b-85ec-bc282ec2afdc).
[Other example with older machine](https://www.youtube.com/watch?v=2XLZ4Z8LpEE).
## Usage
When you open a terminal, you will be greeted by a prompt that will kindly
"ask" you to input a command.
A command is composed of a command name (or verb), and 0, 1, or more arguments.
The verb and each argument are separated by 1 or more spaces.
Just like in English grammar, the arguments have different meanings for
different verbs. For example, when you use the verb `cp` (for "copy"), the
first arguments are the "source" (that is, the files to copy), and the last
argument is the destination:
```bash
# Copies the file "file_1.txt" into "file_2.txt"
user@host:~$ cp file_1.txt file_2.txt
# ^^ ^^^^^^^^^^ ^^^^^^^^^^
# | | |
# | '-------------'- arguments
# |
# '---------------------- command name (verb)
```
But when you use the verb `mkdir` (for "make directory"), all the arguments are
names of directories that you want to create:
```bash
# Create the directories "dir_1", "dir_2", and "dir_3"
user@host:~$ mkdir dir_1 dir_2 dir_3
```
For any new commands you learn, be sure to check the manual by executing the
command `man <command>`. For example, if you want to know more about the
`mkdir` command, you simply have to execute: `man mkdir`.
## Argument conventions
If you are developing a new command-line program, you are free to do anything
you want with the arguments that are passed down to you.
Should you wish it, you could make a program that goes like this:
```bash
# Copies the file "file_1.txt" into "file_2.txt"
user@host:~$ my_cp ~~file_1.txt//file_2.txt~~
# Copies the file "file_1.txt" into "file_2.txt"
# and overwrite "file_2.txt" if it exists
user@host:~$ my_cp ~~file_1.txt//file_2.txt~~ _~overwrite
```
But that would be pretty horrible.
More than the fact that this syntax is hideous, we need a common syntax to
specify options, flags, etc.
And this is where the POSIX convention, and the GNU convention comes in.
It specifies that optional arguments are to be prefixed by `--`, or `-` if it
is just one letter:
```bash
# Copies the file "file_1.txt" into "file_2.txt"
# and overwrite "file_2.txt" if it exists
user@host:~$ cp file_1.txt file_2.txt --force
# Copies the file "file_1.txt" into "file_2.txt"
# and overwrite "file_2.txt" if it exists (using the short option)
user@host:~$ cp file_1.txt file_2.txt -f
```
Some options can also take themselves an argument, by separating them with a
`=`, or just using the following command-line argument:
```bash
# Lists file in the current directory, sorted by size
user@host:~$ ls --sort=size
# Same thing
user@host:~$ ls --sort size
```
Options without an argument are commonly called "flags."
Again, these are still conventions, developers are free to ignore those. To
this day, you can still find programs that don't respect either the POSIX nor
the GNU conventions.
TODO: link to example with https://explainshell.com
## Components
While using the term "command-line" might suggest that it's composed of
a single component, it isn't. Should you have a problem to debug, I always find
it useful to know how the different pieces interact with on another.
So, here are the different pieces that are the most useful to us[^tty]:
[^tty]:
Some components are omitted for simplicity's sake, like the concept of
"tty," "pty," and others
The terminal / terminal emulator
: Renders text on the screen
The prompt / REPL
: A part of the shell that interactively asks for command-lines, and shows you
some information like what user you are logged as, what directory you're
currently in, etc.
The shell
: Interprets command-lines and execute them
### The terminal
As I said above, the terminal (or terminal emulator) is the program that
renders the text on the screen. It's therefore *not* the kind of program I was
talking about in the [purpose] section.
It's a graphical program that creates a new window, runs a text-only program
as a child process, and for each character outputted by the text program,
convert the character into pixels that are rendered in the window for our eyes
to see.
Therefore, if you want to change the font displayed, the terminal is the
program to configure.
"But what kind of child program does the terminal starts?" you might ask. And
that brings us to:
### The prompt
While a terminal emulator is able to run any kind of program, it would be most
useful if it started a program that repeatedly would take a command-line and
execute it.
It would be a pain to start a terminal emulator for each and every little
commands we wanted to execute[^close-on-exit].
[^close-on-exit]:
In fact it's so common to run a prompt in a terminal emulator that most
terminal just closes the window and exit when the text program exits. If
you were to run `mkdir new_dir` as the terminal command, you would see
a new window being created, and it would close after ~0.002 seconds.
And this is why we run an interactive text program: it's just easier, faster,
and way less annoying.
When you first start a terminal in a new installation of a Linux system, you
will mostly likely be greeted with a Bash prompt, Bash being the name of one of
the several shells that exists in this world.
Your prompt will likely resemble this (annotations added):
```bash
# ,------ username you are logged in as
# |
# | ,---- directory you are in,
# | | '~' means your user directory
# vvvv v
user@host:~$
# ^^^^ ^
# | |
# | '--- '$' if you are a normal user,
# | '#' if you are the root user
# |
# '--- name of the machine you are on
```
But just like everything is in the UNIX world, it's very customizable:
- You can for example run a prompt from a different shell: instead of using the
Bash prompt, you can use the one from Zsh, Fish, Csh, Nushell, etc.
- You can customize the prompt itself using the configuration system of Bash,
Zsh, etc.
For example in Bash and many other shells, you can change your prompt by
changing the `$PS1` variable. Try executing this in a Bash shell (you may need
to launch `bash --norc` before):
```bash
PS1='\A \u@\h \w (\s) \$ '
```
Full documentation of the prompt's "special characters"
[here](https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Controlling-the-Prompt).
### The shell
It might seem like the prompt is everything there is about Bash, Zsh, etc., but
these programs are actually much more powerful than that: a shell is
a full-size programming language!
Like any programming language it's very useful for automating tasks, and the
fact that a shell script (a program written in a shell language) is included in
every Linux system, and that it's very quick to write makes it very common in
embedded systems and system administration.
So, let's go over the particularities of the shell programming language.
TODO: move these sections to new "Shell Scripting" article
#### Basic interpretation of a command
```c
#include <stdio.h>
/// The entry point of the program.
///
/// \param argc the number of command line arguments
/// \param argv the command line argument,
/// as an array of NULL terminated strings
int main(int argc, char** argv) {
for(int i = 0; i < argc; ++i) {
printf("Argument %i: %s\n", i, argv[i]);
}
}
```
#### Variables and interpolation
TODO
#### Control flow
TODO
#### The various shell implementations
TODO
## Further reading
TODO
|