exercises/hearing: Replace 2012-04-uchichicago commit with 2012-02-trieste
[swc-modular-shell.git] / instructor.md
1 # Introduction to the shell
2
3 * Name-drop [terminal][] as distinct from [shell][].
4     * Get folks to a terminal.
5 * Mention [Bash][] as a common default shell
6     * If you're in a different shell, run `bash` to get Bash.
7     * Mention commonality between shells, but existence of differences.
8         * Maybe mention [POSIX][].
9     * [Name-drop the Advanced Bash-Scripting Guide][ABSG].
10 * Have them clone the boot camp repository:
11
12         $ git clone -b YYYY-MM-PLACE --single-branch git://github.com/swcarpentry/boot-camps.git
13
14 * `echo` (e.g. `echo Hello, World`)
15     * Remind them to press enter.
16     * Useful for printing from a shell script, for displaying
17       variables, and for generating known values to pass to other
18       programs.
19
20 # File systems
21
22 * `pwd` (print working directory)
23 * `ls` (list directory contents)
24 * Directory/folder equivalence
25 * Directories are just lists of files or other directories.
26 * New-terminals/shells start in the *home* directory.
27     * Every user has their own home directory.
28 * `whoami` (what is my user name)
29
30 # File types
31
32 * `ls` output is colored (run it in the home directory).
33     * Directories are usually blue (customize with `~/.dir_colors`).
34 * `touch` (create an empty file)
35
36         $ touch testfile
37
38 * `ls` again, see `testfile`.  Note that it's white (a general file).
39 * `ls -F`, because some terminals don't support colors.
40     * Directories marked with a trailing slash (/)
41     * Executables marked with a trailing star (*)
42 * `ls -l` to get permissions, ownership, size, modification times, etc.
43     * If the entry is a directory, then the first letter will be a `d`.
44     * The fifth column shows you the size of the entries in bytes.
45         * Notice that `testfile` has a size of zero.
46 * `rm` to remove files and (with `-r`) directories.
47
48         $ rm testfile
49
50 * Run `ls` again, and see that `testfile` is gone.
51
52 # Changing Directories
53
54 * `cd` (change directory) into the directory they'd previously cloned
55
56         $ cd boot-camps
57
58 * `ls` to see what's in the newly current directory
59 * `cd` into the exercises section, then `ls` again, and `ls -F`.
60     * You may want to `cd "$LOC1"; cd "$LOC2"` instead of jumping
61       directly via `cd "$LOC1/$LOC2"`.
62 * `cd` without arguments takes you back to your home directory
63 * Change back into the examples directory
64
65 # Arguments
66
67 * `-F` and `-l` are arguments to `ls`
68 * `ls` takes lots of arguments
69 * `man` pages (when they exist) usually describe these options
70
71         $ man ls
72
73     * `man` displays the page using your `PAGER`.  This is probably
74       `less`.
75
76         * Page down with space or the "page down" key
77         * Page up with `b` or the "page up" key
78         * Search by regexp with `/`
79         * Get help with `h` with other `less` key bindings
80         * Quit with `q`
81
82 * `man find` for a complicated page
83     * Don't worry about learning all of this, just refer back to it as
84       needed.
85
86 ## Exercise: `ls` options
87
88 1. Use the manual page for `ls` to guess what you would expect from
89    using the arguments `-l`, '-t', '-r' at the same time.
90 2. Try the following and see if you can figure out what they do,
91    either by examining the results or consulting the manual page.
92     * `ls -lS` (equivalent to `ls -l -S`)
93     * `ls -lt` (equivalent to `ls -l -t`)
94     * `ls -1`  (that's the number one, not a letter 'ell')
95
96 # Examining the contents of other directories
97
98 * Instead of `cd "$LOC"; ls`, you can use `ls "$LOC"`
99     * Look at a few directories in this repository
100 * Use `cd "$LOC"` to change into a few directories as well
101     * Folks should be comfortable with `cd "$LOC1/$LOC2"` by now
102
103 # Full vs. relative paths
104
105 * Directories are arranged in a single hierarchy, based on the
106   *root directory* `/`.
107 * Full (aka absolute) paths include everything from the root down.
108 * Relative paths don't start with the root directory, and are
109   (usually) interpreted relative to the current working directory
110   (`pwd`).
111 * Examples with full paths:
112
113         $ cd /home/swc/boot-camps/modular
114
115 * Examples with relative paths:
116
117         $ cd
118         $ cd boot-camps/modular
119
120 # Exercise: Listing `/bin`
121
122 List the contents of the `/bin` directory (a full path).  Do you see
123 anything familiar in there?
124
125 # Saving time with shortcuts, wild cards, and tab completion
126
127 ## Path shortcuts
128
129 * `~` for your home directory
130 * `..` for the parent of the current working directory
131 * Chainable.  For example: `ls ../../` or `ls ~/../`.
132 * `.` for the current directory
133     * Equivalent commands:
134         * `ls`
135         * `ls .`
136         * `ls ././././.`
137 * These shortcuts are not necessary, they are provided for your
138   convenience.
139
140 # Example: Cochlear implants
141
142 Introduce the [cochlear implant example][cochlear] to practice with
143 the coming topics.
144
145 ## Wildcards
146
147 * Docs for wildcards are in in glob(7).
148 * For cochlear implants, cd into `data/THOMAS` for this.
149 * `ls`, there are a bunch of files with four-digit names
150 * `ls *`, same list
151 * `ls *1', all files ending with 1
152 * `ls /usr/bin/*.sh`, an absolute path example
153 * `ls *4*1`, compound wildcards
154     * These are expanded *by the shell*, before being passed to the
155       command, so the following are identical;
156
157             $ ls *4*1
158             $ ls 0241 0341 0431 0481
159
160 ### Exercise: Globbing with `ls`
161
162 Do each of the following using a single `ls` command without
163 navigating to a different directory.
164
165 1.  List all of the files in `/bin` that contain the letter `a`
166 2.  List all of the files in `/bin` that contain the letter `a` or the letter `b`
167 3.  List all of the files in `/bin` that contain the letter `a` AND the letter `b`
168
169 ## Tab completion
170
171 * Change to the home directory.
172 * Work back to the coclear implant example data using tab completion
173
174         $ cd b<tab>
175         $ cd boot-camps/
176         $ cd boot-camps/<tab><tab>
177         …list of choices…
178
179 * Tab completion for executables in the `PATH`.
180
181         $ e<tab><tab>
182         $ ec<tab>
183         $ echo
184
185 ## Command History
186
187 * Work through history with up and down arrows.
188 * `^C` to cancel the command you are writing and give you a fresh
189   prompt.
190 * `^R` to reverse-search through your command history.
191 * `history` to print your history
192     * `history | grep …` to grab some useful command
193     * `!123` to reuse the 123rd command in your history
194
195 ### Excercise: History
196
197 1. Find the line number in your history for the last exercise (listing
198    files in `/bin`) and reissue that command.
199
200 ## Which program?
201
202 * `ls`, `rm`, `find`, … are stand-alone programs.
203 * `command`, `shift`, `cd`, `echo`, `pwd`, … are likely shell builtins
204 * `which COMMAND` to look up the command in your `PATH`
205 * `command -V COMMAND` to get useful info:
206
207         $ command -V cd
208         cd is a shell builtin
209         $ command -v find
210         /usr/bin/find
211         $ command -V ls
212         ls is aliased to `ls --color=auto'
213 * Explain `PATH` lookup (`echo $PATH`)
214 * In the example directory, there's a `hello` script
215     * Try to run it with `hello`.  Oops, not in the `PATH`!
216     * Give a path with `./hello`.  Success!
217         * Something that `.` is useful for!
218     * `/home/…/boot-camps/…/hello`
219     * `../exercises/hello/hello`
220     * Only get `PATH` lookups when there aren't any `/` in your command.
221
222 ## Examining Files
223
224 We now know how to switch directories, run programs, and look at the
225 contents of directories, but how do we look at the contents of files?
226
227 * `cat` (concatenate).  In the cochlear implant example,
228
229         $ cat ex_data.txt
230         $ cat ex_data.txt ex_data.txt
231
232 ### Exercise: 
233
234 1.  Print out the contents of the `dictionary/dictionary.txt` file.
235     What does this file contain?
236
237 2.  Without changing directories, use one short command to print the
238     contents of all of the files in the
239     `/home/…/boot-camps/…/exercises/hearing/data/THOMAS` directory.
240
241 ## Paging
242
243 * How to view large files?
244 * `less` (is `more`)
245
246         $ less ~/boot-camps/…/exercises/dictionary/dictionary.txt
247
248 * `less` opens the file and lets you navigate through it.
249 * As mentioned with the `man` page stuff earlier, `h` for help, `q` to
250   quit.
251 * Searches with `/` don't wrap, search from the beginning of the file.
252
253 ### Example: paging through man pages
254
255 Use the commands we've learned so far to figure out how to search
256 in reverse while using `less`.
257
258 ## Redirection
259
260 * Back to the hearing example!
261 * Enter the `Bert` subdirectory.
262 * Print all the experimental results
263
264         $ cat au*
265
266 * Redirect that into a file:
267
268         $ cat au* > ../all_data
269
270 * Examine `all_data` with `less`.
271 * If `all_data` had already existed, we would overwritten it.
272 * `>` tells the shell to take the output from what ever is (stdout) on
273   the left and dump it into the file on the right.
274 * `>>` is the same, but it appends instead of overwriting.
275
276 ### Exercise: Redirection
277
278 Use `>>`, to append the contents of all of the files whose names
279 contain the number 4 in the `gerdal` directory to the existing
280 `all_data` file. Thus, when you are done `all_data` should contain all
281 of the experiment data from `Bert` and any experimental data file from
282 `gerdal` with filenames that contain the number 4.
283
284 ## Creating, moving, copying, and removing
285
286 We've created a file called `all_data` using the redirection operator
287 `>`. This file is critical—it's our analysis results—so we want to
288 make copies so that the data is backed up.
289
290 * `cp` (copy)
291
292         $ cp all_data all_data_backup
293
294 * `mv` (move)
295
296         $ mv all_data_backup /tmp/
297
298     * Explain what `/tmp` is for, and that it doesn't (usually)
299       survive reboots.
300 * Rename with `mv`.
301
302         $ mv all_data all_data_IMPORTANT
303
304 * `rm` (remove)
305
306         $ rm /tmp/all_data_backup
307
308 * `mkdir` (make directory)
309 * By default, `rm`, will NOT delete directories.  Use `-r` (carefully!)
310     * Also, `rmdir` (remove directory)
311
312 ### Excercise: Rename, create, and copy
313
314 1.  Rename the `all_data_IMPORTANT` file to `all_data`.
315 2.  Create a directory in the `data` directory called `foo`
316 3.  Then, copy the `all_data` file into `foo`
317
318 ## Count the words
319
320 * `wc` (word count).  From `hearing/data`:
321
322         $ wc Bert/* gerdal/*4*
323
324 * Three columns for each file:
325     * Number of lines
326     * Number of words
327     * Number of characters
328 * The final line contains this information summed over all of the
329   files.
330 * Check summation:
331
332         $ wc all_data
333
334 * Compare byte size with character count
335
336         $ ls -l all_data
337
338 ### Exercise: Longest line length
339
340 Figure out how to get `wc` to print the length of the longest line in
341 `all_data`.
342
343 ## The awesome power of the Pipe
344
345 Suppose I wanted to only see the total number of character, words, and
346 lines across the files `Bert/*` and `gerdal/*4*`. I don't want to
347 see the individual counts, just the total. Of course, I could just do:
348
349     wc all_data
350
351 Since this file is a concatenation of the smaller files. Sure, this
352 works, but I had to create the `all_data` file to do this. Thus, I
353 have wasted a precious 10445 bytes of hard disk space. We can do this
354 *without* creating a temporary file, but first I have to show you two
355 more commands: `head` and `tail`. These commands print the first few,
356 or last few, lines of a file, respectively. Try them out on
357 `all_data`:
358
359     head all_data
360     tail all_data
361
362 The `-n` option to either of these commands can be used to print the
363 first or last `n` lines of a file. To print the first/last line of the
364 file use:
365
366     head -n 1 all_data
367     tail -n 1 all_data
368
369 Let's turn back to the problem of printing only the total number of
370 lines in a set of files without creating any temporary files. To do
371 this, we want to tell the shell to take the output of the `wc Bert/*
372 gerdal/*4*` and send it into the `tail -n 1` command. The `|`
373 character (called pipe) is used for this purpose. Enter the following
374 command:
375
376     wc Bert/* gerdal/Data0559 | tail -n 1
377
378 This will print only the total number of lines, characters, and words
379 across all of these files. What is happening here? Well, `tail`, like
380 many command line programs will read from the *standard input* when it
381 is not given any files to operate on. In this case, it will just sit
382 there waiting for input. That input can come from the user's keyboard
383 *or from another program*. Try this:
384
385     tail -n 2
386
387 Notice that your cursor just sits there blinking. Tail is waiting for
388 data to come in. Now type:
389
390     French
391     fries
392     are
393     good
394
395 then CONTROL+d. You should is the lines:
396
397     are
398     good
399
400 printed back at you. The CONTROL+d keyboard shortcut inserts an
401 *end-of-file* character. It is sort of the standard way of telling the
402 program "I'm done entering data". The `|` character is replaces the
403 data from the keyboard with data from another command. You can string
404 all sorts of commands together using the pipe.
405
406 The philosophy behind these command line programs is that none of them
407 really do anything all that impressive. BUT when you start chaining
408 them together, you can do some really powerful things really
409 efficiently. If you want to be proficient at using the shell, you must
410 learn to become proficient with the pipe and redirection operators:
411 `|`, `>`, `>>`.
412
413
414 ### A sorting example
415
416 Let's create a file with some words to sort for the next example. We
417 want to create a file which contains the following names:
418
419     Bob
420     Alice
421     Diane
422     Charles
423
424 To do this, we need a program which allows us to create text
425 files. There are many such programs, the easiest one which is
426 installed on almost all systems is called `nano`. Navigate to `/tmp`
427 and enter the following command:
428
429     nano toBeSorted
430
431 Now enter the four names as shown above. When you are done, press
432 CONTROL+O to write out the file. Press enter to use the file name
433 `toBeSorted`. Then press CONTROL+x to exit `nano`.
434
435 When you are back to the command line, enter the command:
436
437     sort toBeSorted
438
439 Notice that the names are now printed in alphabetical order.
440
441 * * * *
442 **Short Exercise**
443
444 Use the `echo` command and the append operator, `>>`, to append your
445 name to the file, then sort it and make a new file called Sorted.
446
447 * * * *
448
449 Let's navigate back to `~/boot-camps/shell/data`. Enter the following command:
450
451     wc Bert/* | sort -k 3 -n
452
453 We are already familiar with what the first of these two commands
454 does: it creates a list containing the number of characters, words,
455 and lines in each file in the `Bert` directory. This list is then
456 piped into the `sort` command, so that it can be sorted. Notice there
457 are two options given to sort:
458
459 1.  `-k 3`: Sort based on the third column
460 2.  `-n`: Sort in numerical order as opposed to alphabetical order
461
462 Notice that the files are sorted by the number of characters.
463
464 * * * *
465 **Short Exercise**
466
467 1. Use the `man` command to find out how to sort the output from `wc` in
468 reverse order.
469
470 2. Combine the `wc`, `sort`, `head` and `tail` commands so that only the
471 `wc` information for the largest file is listed
472
473 Hint: To print the smallest file, use:
474
475     wc Bert/* | sort -k 3 -n | head -n 1
476
477 * * * *
478
479 Printing the smallest file seems pretty useful. We don't want to type
480 out that long command often. Let's create a simple script, a simple
481 program, to run this command. The program will look at all of the
482 files in the current directory and print the information about the
483 smallest one. Let's call the script `smallest`. We'll use `nano` to
484 create this file. Navigate to the `data` directory, then:
485
486     nano smallest
487
488 Then enter the following text:
489
490     #!/bin/bash
491     wc * | sort -k 3 -n | head -n 1
492
493 Now, `cd` into the `Bert` directory and enter the command
494 `../smallest`. Notice that it says permission denied. This happens
495 because we haven't told the shell that this is an executable
496 file. If you do `ls -l ../smallest`, it will show you the permissions on
497 the left of the listing.
498
499 Enter the following commands:
500
501     chmod a+x ../smallest
502     ../smallest
503
504 The `chmod` command is used to modify the permissions of a file. This
505 particular command modifies the file `../smallest` by giving all users
506 (notice the `a`) permission to execute (notice the `x`) the file. If
507 you enter:
508
509     ls -l ../smallest
510
511 You will see that the file name is green and the permissions have changed.
512 Congratulations, you just created your first shell script!
513
514 # Searching files
515
516 You can search the contents of a file using the command `grep`. The
517 `grep` program is very powerful and useful especially when combined
518 with other commands by using the pipe. Navigate to the `Bert`
519 directory. Every data file in this directory has a line which says
520 "Range". The range represents the smallest frequency range that can be
521 discriminated. Lets list all of the ranges from the tests that Bert
522 conducted:
523
524     grep Range *
525
526 * * * *
527 **Short Exercise**
528
529 Create an executable script called `smallestrange` in the `data`
530 directory, that is similar to the `smallest` script, but prints the
531 file containing the file with the smallest Range. Use the commands
532 `grep`, `sort`, and `tail` to do this.
533
534 * * * *
535
536
537 # Finding files
538
539 The `find` program can be used to find files based on arbitrary
540 criteria. Navigate to the `data` directory and enter the following
541 command:
542
543     find . -print
544
545 This prints the name of every file or directory, recursively, starting
546 from the current directory. Let's exclude all of the directories:
547
548     find . -type f -print
549
550 This tells `find` to locate only files. Now try these commands:
551
552     find . -type f -name "*1*"
553     find . -type f -name "*1*" -or -name "*2*" -print
554     find . -type f -name "*1*" -and -name "*2*" -print
555
556 The `find` command can acquire a list of files and perform some
557 operation on each file. Try this command out:
558
559     find . -type f -exec grep Volume {} \;
560
561 This command finds every file starting from `.`. Then it searches each
562 file for a line which contains the word "Volume". The `{}` refers to
563 the name of each file. The trailing `\;` is used to terminate the
564 command.  This command is slow, because it is calling a new instance
565 of `grep` for each item the `find` returns.
566
567 A faster way to do this is to use the `xargs` command:
568
569     find . -type f -print | xargs grep Volume
570
571 `find` generates a list of all the files we are interested in,
572 then we pipe them to `xargs`.  `xargs` takes the items given to it
573 and passes them as arguments to `grep`.  `xargs` generally only creates
574 a single instance of `grep` (or whatever program it is running).
575
576 * * * *
577 **Short Exercise**
578
579 Navigate to the `data` directory. Use one `find` command to perform each
580 of the operations listed below (except number 2, which does not
581 require a `find` command):
582
583 1.  Find any file whose name is "NOTES" within `data` and delete it
584
585 2.  Create a new directory called `cleaneddata`
586
587 3.  Move all of the files within `data` to the `cleaneddata` directory
588
589 4.  Rename all of the files to ensure that they end in `.txt` (note:
590     it is ok for the file name to end in `.txt.txt`
591
592 Hint: If you make a mistake and need to start over just do the
593 following:
594
595 1.  Navigate to the `shell` directory
596
597 2.  Delete the `data` directory
598
599 3.  Enter the command: `git checkout -- data` You should see that the
600     data directory has reappeared in its original state
601
602 **BONUS**
603
604 Redo exercise 4, except rename only the files which do not already end
605 in `.txt`. You will have to use the `man` command to figure out how to
606 search for files which do not match a certain name.
607
608 * * * *
609
610
611
612 # Bonus material
613
614 * Command substitution (`$(command)` and `\`command\``).
615 * `xargs`
616 * Aliases (`rm -i`)
617 * Variables (`PATH`, `PS1`, `PWD`)
618 * `.bashrc`
619 * `du` (disk usage)
620 * `ln` (link)
621 * `ssh` and `scp` (secure shell and secure copy)
622 * Regular expressions (with `grep`, `sed`, …)
623 * Permissions (`ls -l`, `chmod`, `chown`)
624 * Chaining commands (pipes, file descriptors, fifos, …)
625
626
627 [terminal]: https://en.wikipedia.org/wiki/Terminal_emulator
628 [shell]: https://en.wikipedia.org/wiki/Unix_shell
629 [Bash]: http://www.gnu.org/software/bash/
630 [POSIX]: http://pubs.opengroup.org/onlinepubs/9699919799/idx/shell.html
631 [ABSG]: http://tldp.org/LDP/abs/html/
632 [cochlear]: exercises/hearing/