summaryrefslogtreecommitdiffstats
path: root/cli.md
blob: 07a3b73d51619acc78f3af98384972d75fff1bc5 (plain)
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
% The Linux command-line


## 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 is 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]:
	Another possible reason it was created is because computers didn't even
	have screen before, but instead printed text on paper

TODO: link teletypewriter video by Drew Devault


## 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 arguments 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" (i.e. 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 really ugly to look at, 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
```

TODO: we call options without argument a "flag"

TODO: Remind that these are still convention, some programs don't respect that

## Components

While using the term "command-line" might suggest that it is composed of
a single component, it is not. 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 informations 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 is therefore *not* the kind of program I was
talking about in the [purpose] section.

It is 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 is 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, everything about it is
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, etc.
- You can customize the prompt itself using the configuration system of Bash,
  Zsh, etc.

TODO: link doc of bash 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 is 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 is 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.

#### 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

#### Control flow

#### The various shell implementations

## Further reading