aboutsummaryrefslogtreecommitdiff
path: root/content/weblog/2018-12-31_intro-to-linux-and-bash-pt2/index.md
blob: 5739e066b10fa862cb29f3bac7949252363a99e0 (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
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
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
+++
title = "Intro to Linux and the Bash command line, pt II"
date = 2018-12-31T09:20:00Z
+++

So the year is coming to an end, and I didn't follow up on the first part of
these mini tutorial/guide/introduction. Might as well end the year on a good
note and write at least one post this last month.

<!-- more -->

In this part I will be writing about some more aspects of Linux and Unix-like
systems and tools that will come in handy when using the terminal. All or most
of these tools are a standard part of Linux and Unix/Unix-like systems.

## File manipulation

I didn't get into detail in the previous part of this guide on the file
manipulation side of things. However it is a crucial part of any computer
system, after all they wouldn't be as useful as they are if you couldn't create,
edit and delete files.

### Create files

Usually, the way you would go about creating and editing files is by using the
corresponding programs. Like for example, vim to create and edit text files.
However, there's also a utility to create blank files called touch.

You can make a blank file by writing touch followed by the path of the file you
wish to create, like this

```sh
user@host:~$ touch example.txt
```

Now we have an empty file at "/home/user/example.txt". Although I kind of lied
when I said that this command is for making blank files. In reality, what it
does is check if such file exists, if it does, it modifies the date and time of
access and modification, otherwise it makes a new empty file, like in our case.
Most of the time you won't really need this command, since you would actually be
creating files through programs or means, though it does come in handy
sometimes.

### Create directories

Now on to something more interesting, making directories. This one is quite
simple, and the command for that is mkdir. For example

```sh
user@host:~$ mkdir foo
```

In this case we have created a new folder called "foo" in "/home/user/". But
remember that we are passing paths here, which can be relative or absolute (if
you don't know or remember what this means, check the first part of this guide).
In our case  we were using a relative path, with just the name of the directory
to create.

If we were to indicate an absolute path like "/home/user/foo" we would need to
make sure that directories "home" and "user" already exist. However, there's a
useful argument we can pass to mkdir to make parent directories if needed, -p

```sh
user@host:~$ mkdir -p /tmp/foo/bar
```

In this case, if directory "foo" doesn't exist, mkdir will make it for us along
with "bar" inside it.

### Moving and renaming

This one is pretty simple, and both actions are handled by the same command, mv,
which is short for move.

If you want to rename a file or directory, simply "move" it to the same
destination directory with a new/different name, for example

```sh
user@host:~$ mv untitled titled
```

If you want to move it to a different location, just indicate that path as the
second argument. Remember that we are using paths here, and we use either
absolute or relative paths

```sh
user@host:~$ mv titled Documents/titled
```

### Copying

Copying files is similar to moving them, except that the command is different,
cp

```sh
user@host:~$ cp titled Documents/titled2
```

However, copying directories is different. To copy directories you have to use a
special flag, the -r flag. This flag means that the operation ought to be
recursive, that is to copy every file and subdirectory in that directory along
with the directory (and files in those subdirectories and files the
subdirectories of the subdirectories and... yeah recursion, you get it) to the
destination path. So we would do something like this

```sh
user@host:~$ cp -r dir dir-copy
```

### Removing

Removing files is pretty simple, just use rm followed by the path of the file,
for example

```sh
user@host:~$ rm title
```

However, removing directories is a little bit trickier. One option would be to
use the command rmdir, however, the directory has to be empty before you can
remove it.

The second option, is to use the same command as we used with files, but passing
it the -r flag so that it removes files recursively, similar to what we did with
the copy (cp) command. Do watch out, as it will remove the directory along with
everything that is in it.

So to remove a directory and everything in it, we input something like this

```sh
user@host:~$ rm -r dir
```

This command also has another flag to forcefully remove files without prompting,
the -f flag. This might be useful when you are removing files recursively and
there might be some special files, like hidden files (the ones with a dot as the
first character) and you don't want to be prompted for each and everyone of
them.

Thread REALLY carefully when using this command though, especially if you are
issuing it as root. You don't wanna issue a "sudo rm -rf /" and end up with a
borked system and lost files. Unless you are some kind of sadist or something.

An example of when it might be useful, is when you need to delete a git
repository from your computer, since it contains a lot of special hidden files
which git uses to keep track of your commits and other stuff. So to remove it,
we do

```sh
user@host:~$ rm -rf somerepo
```

### Permissions

The Unix or Unix-like user and permissions systems, is a robust system for
managing what particular users can do with certain files and directories. This
allows to create a secure environment, especially when there are multiple users
using one computer.

Every file has three types of permissions which dictate what can be done with
it. Each permission is represented by a single letter

* r - read: the user can read/view the file.
* w - write: the user can write/modify (this includes deleting) the file.
* x - execute: the file can be run or executed by the user, if it is a program
  or script.

There are as well three different sets of people the permissions and ownership
might apply to. These are

* u - user/owner: the one user that owns the file. Usually it is the user that
  created the file, but ownership can be modified.
* g - group: every file has a group it belongs to. The group can be a one user
  group (every user has their own one-user group), or a common group with
  multiple users.
* o - others: everybody else who is not either in the group or the owner.

If you read the first part of this guide you might remember that I mentioned
using the command "ls -l" to list the contents of the directory with details
about the files, including permissions

```sh
user@host:~/Documents$ ls -l
drwxr-xr-x  2 user user  4.0K Jul  18 04:20 Books
-rwxr-xr--  1 user group 350  Jul  18 04:20 run.py
-rw-r--r--  1 user user  1.2M Jul  18 04:20 picture.png
```

As mentioned in the first part, the first ten characters of a row of the output
is what tells us about the permissions of the given file in that row.

The first character in that sequence tells us if it is a normal file, or a
directory. If it has a d, it is a directory (duh), if it has a dash, it is a
normal file. It can be another letter, like an l for a symbolic link (a topic
for another day).

The next 9 characters are divided in subsequences of three letters, each for a
set of people. The first three characters after the file type one are the
permissions for the owner, the next three are for the group, and the last three
for others.

In each of this subset of three characters, the permissions are in the order of
read, write, and execute. So a letter means that that said set of users have
said permission, and its absence means the lack of that permission.

Let's take for example the "run.py" file. By the information there we can see
that it is a normal file (no d (that's what she said)), its owner (user) can
read, write and even execute it; the group users (in group group) can read and
execute it, but not write to it; and the others can just take a look at its
contents.

You might have noticed that directories tend to have the "x" part of the
permissions, however, this means something a little bit different on directories
than on files. It doesn't mean that you can execute but rather that you can
"search it", or in other words, access files inside of it. Because having the
"read" permission on a directory only means that you can take a look at what
files are inside of it, and write that you can put files inside the directory.

### Changing permissions

There is a really useful command that allows us to change permissions on files,
chmod. It is short for change file mode bits.

To change the permissions on the file you input chmod followed by the
permissions and the path of the file. There are two ways of setting the
permissions, the easy and long one using letters, and the short but not as easy
way with octal "permission bits". We'll take a look at the easy one first.

The easier way is made up of three parts

* Who - user/owner, group, others or all (u, g, o, or a)
* Revoke or grant, "+" to grant, "-" to revoke
* The permission we are setting - read, write or execute (r, w, or x)

So let's suppose we have a script we want to set the execute permission for so
that any user in the computer can execute it.

```shh
user@host:~/Documents/stuff$ ls -l
-rw-r--r-- 1 user group  420  April 20 6:59  script.sh
user@host:~/Documents/stuff$ chmod a+x script.sh
-rwxr-xr-x 1 user group  420  April 20 6:59  script.sh
```

As we can see, after executing the command, every user on the computer now has
execute permission on the script. Now let's say that we want to revoke read
permissions for everybody except for the owner (user), we could execute o-r and
then g-r, but we can also combine them, like so

```sh
user@host:~/Documents/stuff$ chmod go-r script.sh
-rwx--x--x 1 user group  420  April 20 6:59  script.sh
```

Now onto the short way. This one's a bit harder to remember as you have to have
some understanding of binary. Basically the way it works is that you set the
permissions by passing three octal numbers (i.e., 0-7) that each represent the
permission bits for each set of people (user/owner, group, others).

As it is we have three possible permissions (read, write and execute) and 2^3
just so happens to be 8 (possible combinations), that's why it is in octal.
Here's a table to help you out


<table>
  <tbody>
    <tr>
      <td>Octal</td>
      <td>Binary</td>
    </tr>
    <tr>
      <td>0</td>
      <td>001</td>
    </tr>
    <tr>
      <td>1</td>
      <td>001</td>
    </tr>
    <tr>
      <td>2</td>
      <td>010</td>
    </tr>
    <tr>
      <td>3</td>
      <td>011</td>
    </tr>
    <tr>
      <td>4</td>
      <td>100</td>
    </tr>
    <tr>
      <td>5</td>
      <td>101</td>
    </tr>
    <tr>
      <td>6</td>
      <td>110</td>
    </tr>
    <tr>
      <td>7</td>
      <td>111</td>
    </tr>
  </tbody>
</table>

Basically what this means, is that when we have a 1, said permission is granted,
when it is 0, it is not. So for example, 6 means that read and write have been
granted, but not execute, because 6 => 110 => rw-.

So let's say for example that we want to set the permissions of file so that the
owner can read, write, and execute, the group can read and execute, and others
can only execute. It would look something like this

```sh
user@host:~/Documents/stuff$ chmod 751 script.sh
user@host:~/Documents/stuff$ ls -l
-rwxr-x--x 1 user group  420  April 20 6:59  script.sh
```

If you are changing the permissions of a directory, the permissions will apply
only to the directory itself and not to the files and subdirectories inside of
it, unless you use the recursive flag -R (note that in the case of chmod and
chown it is a capital R).

### Changing ownership

Changing the owner of a file is easier than changing permissions, since less
variables are involved. To change owner we use the chown command, for example,
change the user that owns a file

```sh
user@host:~/.logs$ ls -l
-rw-r--r-- 1 root root  69  April 20 6:59  some.log
user@host:~/.logs$ sudo chown user some.log
user@host:~/.logs$ ls -l
-rw-r--r-- 1 user root  69  April 20 6:59  some.log
```

As the file doesn't belong to the same user initially, we need to use sudo
elevate our permissions to "super user". Note that in order to be able to use
sudo or "elevate your permissions" your user needs to be either in the sudoers
file or in other distros in the "wheel" group, or both. I won't go into details
on how to do that, since most probably your user is already in the sudoers file,
and a quick search on the internet will give you the information needed.

Now let's say that you wanted to change both the user and group that file
belongs to, we would do like this

```sh
user@host:~/.logs$ ls -l
-rw-r--r-- 1 root root  69  April 20 6:59  some.log
user@host:~/.logs$ sudo chown user:group some.log
user@host:~/.logs$ ls -l
-rw-r--r-- 1 user group  69  April 20 6:59  some.log
```

Just as with chmod, if you want to change ownership recursively in a directory,
you need to use the -R flag.

## Epilogue/Some tips

I forgot to mention in the previous part how to write paths with spaces. You
cannot write paths with spaces just like that, since spaces are treated as the
separator between arguments.

There are two ways of writings paths and filenames (and other arguments) with
spaces. One is to put the argument between quotation marks, like for example

```sh
user@host:~/Documents$ rm "Shopping List.txt"
```

Another is to use an escape character, i.e. just put a backslash (\) before the
space, like this

```sh
user@host:~/Documents$ rm Shopping\ List.txt
```

One more thing that I wanted to mention is the man(ual) pages. Basically all
Linux distros come with man pages.

You don't always have to resort to the internet if you don't remember how to use
a command, like what flags a command accepts, what are the order of the
arguments, etc. You might not have internet one day, and you might to resort to
good ol' offline resources, and the man pages are a good one.

Besides, it is sometimes faster and easier to not have to leave the terminal to
look up the information.

To read the man(ual) pages of a command, input "man" followed by the name of the
command, e.g. "chmod", and it will provide you with almost all the information
that you need.

You can use vim keys (hjkl), or the arrow keys to scroll. Type /<word> to search
for that word, and afterwards press n to find the next found item.

This is all for this part. Happy 2019!