This repository was archived by the owner on Jul 8, 2020. It is now read-only.
forked from stevepettifer/COMP101
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathintro4.tex
More file actions
998 lines (804 loc) · 41.5 KB
/
intro4.tex
File metadata and controls
998 lines (804 loc) · 41.5 KB
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
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
%\chapter{Collaborative tools}
\renewcommand{\tilde}{\textasciitilde}
\newcommand{\moodle}{Moodle}
\newcommand{\Moodle}{Moodle}
\begin{firstonly}
\chapter[Blackboard Intro and command line skills]{Introduction to Blackboard and command line skills}
\minitoc
\notesurl{intro4}
\end{firstonly}
%\begin{note}
% This is the fifth, two hour, lab.
%
% Has change of position (?) of this lab made any difference to how we tell students about first tutorial? Yes --fixed
%
% Do we need some breakout boxes in this script?
%
% \textbf{Steve's wish list}
% \begin{itemize}
% \item better navigation---more cd, pushd, popd, mkdir etc
% \item
%wildcards (use echo)
%\item
%fortune | cowsay
%run fortune lots of times to make file
%\item
%ls m * vs ls m*
%\item
%revisit handy command line tricks
%\item where do we introduce dot (as in ./splunge)
%
% \end{itemize}
%
%
%\end{note}
\input{intro4-Bb.tex}
\section{Reinforcing your command line skills}
\newcommand{\ilinput}[1]{\ttout{#1}}
% \newcommand{\crsname}{COMP10120}
% \newcommand{\Dcrsname}{\fname{/opt/info/courses/COMP10120}}
% \newcommand{\crsnamelc}{comp10120}
\newcommand{\crsname}{INTRO}
\newcommand{\Dcrsname}{\fname{/opt/info/courses/INTRO}}
\newcommand{\crsnamelc}{intro}
\newcommand{\return}{\relax}
This section is designed to help you practise your command line skills in preparation for next week's start of regular lab activities. You've already used most of these commands in previous labs, but please don't rush through this section since we'll be explaining their behaviour in a bit more detail, and introducing you to some of the extra options they provide, as well as some of the pitfalls that lie in wait for the over-zealous command line user.
You've probably figured this out already, but it's worth making explicit here: for Unix commands, it's usually the case that no news is good news. So when you run a program from the shell, if you get no response other than your command-prompt back, that almost always means that the command has done what you asked it to (whether you asked it to do what you \textit{wanted} it to do is, of course, an entirely different matter!). Generally speaking, for most simple Unix commands, you can assume that the absence of an error message means that something has worked. And of course, if you get an error or warning message back from a command, it is crucially important that you read it, understand it, and act on it, rather than just ploughing on regardless. If you ignore errors and warnings, bad things happen. This is true in the Unix command world, and probably isn't a bad philosophy for life in general either.
Anyway, back to the exercise and some practice of manipulating files and directories. In previous labs you've already encountered three directories of particular interest:
\begin{itemize}
\item The \concept{root directory} (\ttout{/}) is the top level of the
\concept{file system}.
%??? file system or filesystem ???
\item Your \concept{current working directory} which is the one you are `in'
at the moment (and is shown by the output from \cmdname{pwd}). This can also
be referenced using a single dot (\ttout{.})\firstorpgt{, as you did when starting up Quake Arena using
\ttout{./ioquake3.arm} in your first Pi lab.}{}
\item Your \concept{home directory} (\ttout{\tilde}) which is the top level of
your own filestore and where \cmdname{cd} (\concept{change directory}) with no
arguments will take you. The value of this is also available as
\ttout{\$HOME}, so the following all have the same effect:
\begin{ttoutenv}
\$ cd
\end{ttoutenv}
or
\begin{ttoutenv}
\$ cd \textasciitilde
\end{ttoutenv}
or
\begin{ttoutenv}
\$ cd \$HOME
\end{ttoutenv}
And no matter what is your current working directory, you can list the files
in your home directory with either of these commands.
\begin{ttoutenv}
\$ ls \textasciitilde
\end{ttoutenv}
or
\begin{ttoutenv}
\$ ls \$HOME
\end{ttoutenv}
\end{itemize}
You should recall the difference between an \concept{absolute path} (one
that starts with a \ttout{/}) and a \concept{relative path} (one that does not
start with \ttout{/} but is instead `found' relatively by starting from the
current working directory). You've met the `double dot' notation
(\ttout{..}) to mean `go up one level', as in \ttout{ls ..} or perhaps more
often \ttout{cd ..}, or even \ttout{cd ../x/y} and so forth.
Speaking of \cmdname{ls}, you will from time to time need to use its
\ttout{-a} switch argument to ask it to show `hidden' files beginning with a dot,
and/or \ttout{-l} (a letter \ttout{l}, not a digit \ttout{1}) to make it show details about the files it lists.
\subsection{Creating a directory structure}
Use the \cmdname{mkdir} (\concept{make directory}) command
to create some directories. Type:
\begin{ttoutenv}
\$ cd
\$ mkdir \crsname\return
\end{ttoutenv}
%
and check that this directory has indeed appeared using \cmdname{ls}.
It's important that directories we ask you to make for your work have
exactly the names we specify: Unix will let you use any names you
like, but so that lab staff know where to look for work when you get marked, and so that the system you'll be using to submit your work knows what you're submitting, it's very important that you follow these conventions for your lab work. Any files and directories you create for your own purposes outside of lab work can of course be named and organised however you like.
If you made a mistake, e.g. \fname{\crsnamelc} instead of \fname{\crsname},
you can remove the directory \textit{while it is still empty} with the
\cmdname{rmdir} command: e.g.
%
\begin{ttoutenv}
\$ rmdir \crsnamelc\return
\end{ttoutenv}
%
And then try to make it correctly.
%The \cmdname{cd} (\concept{change directory}) command allows you to move around
%the tree by changing your current working directory. Type
%%
%\begin{ttoutenv}
%\$ cd \crsname\return
%\end{ttoutenv}
%%
%to make \crsname{} your working directory. Check that you have changed
%current directory using \cmnd{pwd}{pwd}.
Now go into your \ttout{INTRO} directory and let's make some directories for four imaginary \crsname{} exercises.
\begin{ttoutenv}
\$ mkdir ex1 ex2 ex3 ex4\return
\end{ttoutenv}
% mkdir ex1 ex2 ex3 ex4 \return
%
%Recall that the \cmdname{cd} command on its own takes you back to your home
%directory, wherever you may be when you invoke it. Try this out by
%typing
%
%\begin{ttoutenv}
%\$ cd \return
%\end{ttoutenv}
%
%Check that you are now in your home directory.
Now return to your home directory.
Your directory structure should now look something like this:
%\begin{firstonly}
\begin{center}
\includegraphics[width=0.6\textwidth]{images/intro-dir-structure}
\end{center}
%\end{firstonly}
The easiest way to check this is to use
\cmdname{ls} from your home directory with the \ttout{-R} flag. This shows the whole tree
below your current working directory (as with other commands we've encountered before such as \cmdname{chmod}, here the \ttout{-R} is short for
\wikipedia{Recursion}{recursively}---if you've not looked up what this means yet, now is a good time to do that).
\begin{ttoutenv}
\$ ls -R
\end{ttoutenv}
%
\begin{firstonly}
Next make a directory in your home directory for the
\courseunit{COMP16121} course unit with sub-directories for each of the 10
exercises associated with that course (these aren't imaginary exercises, you'll be starting on them next week). You \emph{must} use the same
convention as above: capital \texttt{COMP16121} and lower case \texttt{ex1} and so on.
You must get your directory structure right before continuing---be extremely careful that you get this right.
%ask a member of the lab staff to check it at this point.
%\begin{note}
%Do we really want them all to ask a demonstrator?
%\end{note}
%Every directory is created with two files already there, called `.'
%and `..'. Of course, you don't see them when you run \cmdname{ls}
%because they start with a dot! Now run the command which will enable
%you to see them in your current directory.
%
%`.' is a reference to the directory itself, and `..'is a reference
%to the directory above it in the tree. This may seem rather bizarre at
%first, but they are in fact extremely useful. `..', for example,
%enables you to specify a \emph{relative} pathname \emph{up} the tree.
Now try the following sequence of \texttt{cd}s, checking where you are by running \cmdname{pwd} after each one, and make sure you understand what is going on: if you're at all unsure about what has happened, please grab a member of lab staff to get an explanation---it really will save you a lot of hassle in the long run.
\begin{ttoutenv}
cd \return
cd \crsname/ex1 \return
cd .. \return
cd ex2 \return
cd ../ex1 \return
cd ../../\crsname/ex2 \return
cd ../.. \return
\end{ttoutenv}
%
\end{firstonly}
\subsection{Copying, moving, and removing files}
This subsection re-introduces three commands used for copying, moving and
removing files. We'll first describe each command and then you'll get an opportunity to practise using them.
\subsubsection{Copying files: cp}
\noindent The \cmdname{cp} (copy) command has two forms.
% \begin{note}
% fix $<$file$>$ [file] notation
% \end{note}
The first general form is
\begin{ttoutenv}
\$ cp [FILENAME] [FILENAME] \return
\end{ttoutenv}
For example
\begin{ttoutenv}
\$ cp file1 file2 \return
\end{ttoutenv}
%
makes a copy of the file \fname{file1} and calls it \fname{file2}. If
a file called file2 already exists, \emph{the existing \fname{file2} will be overwritten
with a copy of \fname{file1} and lost without warning}. Using the \ttout{-i} option to \ttout{cp} will ask you if this is about to occur.
%% mention -i
The second form is slightly different:
\begin{ttoutenv}
\$ cp [FILENAME(S)] [DIRECTORYNAME]
\end{ttoutenv}
%
For example
\begin{ttoutenv}
\$ cp file1 file2 file3 dirname \return
\end{ttoutenv}
This copies the files \fname{file1}, \fname{file2} and \fname{file3} into
the directory \fname{dirname}, again overwriting any files already
there with the same names.
\subsubsection{Removing/deleting files: rm}
The command \cmdname{rm} (remove) is used to delete files.
\begin{ttoutenv}
\$ rm [FILENAME(S)]
\end{ttoutenv}
%
throws away the specified files. Always take great care when using \cmdname{rm}: unlike putting things in the `trash' or `recycle bin' in a desktop environment, the effects of \cmdname{rm} are \textit{not reversible}, and you don't get any warning before files are \textit{deleted forever}. Like \ttout{cp}, \ttout{rm} has a \ttout{-i} option which asks you if you really mean it. This option can be particularly useful if you are using wildcards in you command line arguments.
\subsubsection{Moving / renaming files: mv}
The \cmdname{mv} (move) command is similar to \cmdname{cp}, but it just moves
the files rather than makes copies. Again we have the two forms
\begin{ttoutenv}
\$ mv [FILENAME] [FILENAME] \return
\end{ttoutenv}
and
\begin{ttoutenv}
\$ mv [FILENAME(S)] [DIRECTORYNAME] \return
\end{ttoutenv}
The effect is similar to copying followed by removing the sources of the copy,
except it is more efficient than that (most of the time).
For example
\begin{ttoutenv}
\$ mv file1 file2 \return
\end{ttoutenv}
is like doing
\begin{ttoutenv}
\$ cp file1 file2 \return
\$ rm file1
\end{ttoutenv}
and
\begin{ttoutenv}
\$ mv file1 file2 file3 dirname \return
\end{ttoutenv}
is like doing
\begin{ttoutenv}
\$ cp file1 file2 file3 dirname \return
\$ rm file1 file2 file3
\end{ttoutenv}
Using \ttout{mv} will preserve the timestamps on files, whereas the combination of \ttout{cp} and \ttout{rm} will not, since new files are being created.
\begin{diversion}{Taking out the trash}
You now know enough about the behaviour of the filesystem to know what's actually going on when you put files in the `recycle bin' or `trash can' in a desktop environment such as you get with OS X, Windows or Gnome. When you `move to trash' in these environments, you're not deleting the file but instead using an equivalent of the \cmdname{mv} command to move the file from its current location into a special directory that represents the trash can. When you tell the graphical environment to `empty trash', you're actually invoking something equivalent to \cmdname{rm}, which actually does delete the file from the filesystem.
\end{diversion}
%\begin{note}
%
%This seems a bit of an odd thing to put in a section about mv. Do we still want to say this?
%
%Before continuing, answer this question and check your answer with a
%member of staff: how do you \emph{rename} a file in Unix? Don't guess---you
%know the answer, unless you have already forgotten from previous labs and you are now going too fast.
%\end{note}
\subsection{Practice makes perfect}
Now for some practice. Go to your home directory by typing:
%
\begin{ttoutenv}
\$ cd \return
\end{ttoutenv}
%
and copy the file called \fname{fortunes} in the \fname{/usr/share/games/fortune}
directory to your current working directory, by typing
\begin{ttoutenv}
\$ cp /usr/share/games/fortune/fortunes \textbf{.} \return
\end{ttoutenv}
%
Note that the dot (meaning, of course, your current directory) is
essential. If you now do an \cmdname{ls}, you should see that the
file called \fname{fortunes} has appeared in your directory:
\begin{ttoutenv}
\$ ls \return
\end{ttoutenv}
If no file called \fname{fortunes} has appeared, the following will
probably provide an explanation. If it did appear, read this anyway, just to
check that you understand what you did right.
The \cmdname{cp} command needs at least \emph{two} arguments. In this case, the file
you are copying is \fname{/usr/share/games/fortunes}, and the directory
you are copying it to is `.' (that is, your current working
directory; remember every directory has a reference to itself within
it, called `.') If you missed out the dot, or mis-spelt
\fname{/usr/share/games/fortunes}, or missed out one of the spaces, it
won't have worked. In particular, you may well have got an error message like:
%
% Usage: cp [-ip] f1 f2; or: cp [-irp] f1 ... fn d2
\begin{ttoutenv}
cp: missing destination file
Try `cp --help' for more information.
\end{ttoutenv}
%
or
\begin{ttoutenv}
cp: /usr/share/games/fortunes/frotunes: No such file or directory
\end{ttoutenv}
%
If you get the first message, it means you used the command with the
wrong number of arguments, and nothing will have happened.
The other is an example of what you might see if you mistype the first
argument. If you do get an error message you need to give the command again,
correctly, to copy the fortunes file across.
\begin{linux}{fortune}
\label{breakbox:fortune}
At the moment we're just going to be using the fortunes file as something to copy and move around, so its contents are not important, but it's one of the source files used by the Unix \wikipedia{Fortune_(Unix)}{fortune} command, which we will be playing with later.
\wikipedia{Fortune_(Unix)}{fortune} is a simple program that displays a random message from a database of (supposedly) humorous quotations, such as those that can be found in the US in \wikipedia{Fortune_Cookies}{fortune cookies} (hence the name). It also contains jokes (of a sort!) and bits of poetry.
\end{linux}
You should now have a copy of the file in your home directory.
You'll have to get into the habit of \emph{not} having all your files
in your home directory, otherwise you will quickly have an enormous list
of stuff that will take you ages to find anything in. The use of subdirectories
provides a solution to this problem, which is why you created some
earlier. Moving this file to the `correct' place gives you a chance
to practise the \cmdname{mv} command.
Move the file \fname{fortunes} to your \fname{\crsname/ex4} directory.
% Notice that \fname{\crsname} is \emph{your\/} \crsname{} directory, while
% \fname{\Dcrsname} is (an abbreviation for) \emph{our\/} \crsname{}
% directory, from which you can read things but cannot write to.
Now go to your \fname{\crsname/ex4} directory and check that the file
has appeared there.
To make sure you understand \cmdname{cp}, \cmdname{mv}, and
\cmdname{rm}, go through the following sequence (in your
\fname{\crsname/ex4} directory), checking the result by looking at the
output from \cmdname{ls} at each stage:
\begin{ttoutenv}
\$ cp fortunes fortune1 \return
\$ ls \return
\$ cp fortunes fortune2 \return
\$ ls \return
\$ mv fortune1 fortune3 \return
\$ ls \return
\$ cp fortune3 fortune4 \return
\$ ls \return
\$ rm fortune2 \return
\$ ls \return
\$ rm fortune1 \return
\$ ls \return
\end{ttoutenv}
%\begin{note}
%Should these be fortune1 instead of fortune1? There's really no need to abbreviate names is there? and we may be starting off bad habits when it comes to naming files and variables?
%\end{note}
You'll notice that \ilinput{rm fortune1} behaves differently to \ilinput{rm fortune2}; if you can't figure out why, ask a member of lab staff for help.
\subsection{Wild cards}
An asterisk (commonly referred to as \concept{star}) in a filename is a \textbf{wild card} which matches any sequence of
zero or more characters, so for instance, if you were to type (don't
actually do it!)
%
\begin{ttoutenv}
\$ rm *fred*\return
\end{ttoutenv}
%
then all files in the current directory whose names contain the string
`fred' would be removed.
Try the effect of
%
\begin{ttoutenv}
\$ ls fortune*\return
\end{ttoutenv}
%
and
%
\begin{ttoutenv}
\$ ls *tun*\return
\end{ttoutenv}
Now try
%
\begin{ttoutenv}
\$ echo *tun*\return
\end{ttoutenv}
%
Our previous use of \ttout{*} has always been in conjunction with \cmnd{ls}{ls} which might have led you to think that the wild card was being expanded by \cmnd{ls}{ls}. In fact the expansion is done by the \emph{shell}, \cmnd{bash}{bash}, which means that the effect is true for anything you type on the command line. Wildcards are a very powerful and useful feature of the command line, and as with anything powerful and useful can be used or mis-used, so it's important that you know what you're doing with them.
One place where you must take care with wild cards is the dotfiles---these are files
whose names begin with a dot (\ttout{.}), because the asterisk will not match a
\ttout{.} at the start of a file name. To see what this means try the following
\begin{ttoutenv}
\$ cd \return
\$ ls *bash* \return
\end{ttoutenv}
%
and
%
\begin{ttoutenv}
\$ ls .*bash*\return
\end{ttoutenv}
and see the different output.
\subsection{Quotas}
The command
\begin{ttoutenv}
\$ quota\return
\end{ttoutenv}
shows you what your file store quota is, and how much of it you are
actually using. This is only of academic interest now, but may become
very important later in the year! You may find that you are unable to
save files if you use more than your quota of
file store. It is important that, if this happens, you do something
about it immediately.
\subsection{Putting commands together}
\subsubsection{Redirection}
Before you forget that you're in your home directory, change back to
your \ttout{\crsname/ex4} directory.
One of the simplest (and most useful) of Unix commands is
\cmdname{cat}. This command has many uses, one of which is to
con\textbf{cat}enate a list of files given as arguments and display
their contents on the screen. For example:
\begin{ttoutenv}
\$ cat file1 file2 file3 \return
\end{ttoutenv}
would display the contents of the three files \fname{file1},
\fname{file2} and \fname{file3}.
The output from \cmdname{cat} goes to what is known as the
\textbf{standard output} (in this case the screen).
If you type:
\begin{ttoutenv}
\$ cat \return
\end{ttoutenv}
nothing will happen because you haven't given a file to \cmdname{cat}.
When run like this, it takes its data from the \textbf{standard input}---which in this case is the keyboard---and copies it to the standard
output. Anything that you now type will be taken as input by
\cmdname{cat}, and will be output when each line of the input is
complete. In Unix, end of input is signalled by \ctrl{d}.
(Recall that typing \ctrl{d} in your login shell will log you
out---you have told the shell to expect no more input). So, after
typing \cmdname{cat} above, if you type:
\begin{ttoutenv}
The cat
sat
on the
mat
\end{ttoutenv}
and then press \ctrl{d} you will see the input replicated on the output (interleaved line by line with the input). The first copy is the `echo' of what you typed as
you typed it, the second copy is output from \cmdname{cat}. This may
not seem very useful, and you wouldn't actually use it just like that,
%(An example where you really would have cat do just this is a bit too
%complicated to show here!)
%We've merely asked you to do that to
but it illustrates the point that \cmdname{cat} takes its input and copies it
to its output. Using this basic idea we can do various things to
change where the input comes from and where the output goes.
\begin{ttoutenv}
\$ cat > fred1
\end{ttoutenv}
will cause the standard output to be directed to the file \fname{fred1}
in the working directory (the input still comes from the keyboard and
will need a \ilinput{<ctrl>d} to terminate it. Try creating a file
\fname{fred1} using this technique, and then check its contents.
\begin{ttoutenv}
\$ cat < fred1
\end{ttoutenv}
will take the standard input from the file \fname{fred1}
in the working directory and make it appear on the screen. This has
exactly the same effect as
\begin{ttoutenv}
\$ cat fred1
\end{ttoutenv}
You can, of course, use $<$ and $>$ together, as in
\begin{ttoutenv}
\$ cat < fred1 > fred2
\end{ttoutenv}
which will copy the contents of the first file to the second. Try this and
check the results.
We can, of course, do this type of redirection with other
commands. For example, if we want to save the result of listing a
directory's contents into a file we just type something like:
\begin{ttoutenv}
\$ ls -l > fred1
\end{ttoutenv}
(this overwrites the previous contents of \fname{fred1} without
warning, so be careful of this kind of use).
% One of the other things that \cmdname{cat} can do is to put line
% numbers on its output. It does this if you use the \ilinput{-n}
% flag. Try
% \begin{ttoutenv}
% \$ cat -n fred1
% \end{ttoutenv}
% Now suppose, for the sake of argument, we wanted to have a listing of the
% names of the
% files in the current directory, with each line numbered, and the result
% saved in a file \cmdname{fred3}. You have just been given all the
% information you need to do this---so, how would you do it? Do it now.
% Unless you've met Unix before, you probably did something like this
% \begin{ttoutenv}
% \$ ls > tmpfile
% \$ cat -n tmpfile > fred3
% \end{ttoutenv}
% Or if you didn't then try it now and examine the contents of
% \fname{fred3}. The file \fname{tmpfile} can now be thrown away using
% \ilinput{rm tmpfile}.
% It's a shame we had to use an extra, temporary, file. Could we avoid
% having to? Why do you think the following would not work?
% \begin{ttoutenv}
% \$ ls > fred3
% cat -n fred3 > fred3
% \end{ttoutenv}
% A better way of doing the task, which avoids the use of a temporary file
% is by use of a powerful Unix feature called the \textbf{pipe}. We just type
% \begin{ttoutenv}
% \$ ls | cat -n > fred3
% \end{ttoutenv}
\firstorpgt{In the previous Intro lab session}{Earlier} we met the idea of a \concept{pipe}, using the \verb+|+ symbol to connect the \concept{standard
output} of one command to be \concept{piped} to the
\concept{standard input} of a second.
We can construct another (admittedly rather artificial) pipeline example using
just \cmdname{cat}:
\begin{ttoutenv}
\$ cat < fred1 | cat > fred2
\end{ttoutenv}
The first \cmdname{cat} takes its input from the file
\fname{fred1} and sends its output into the pipe. The second
\cmdname{cat} takes its input from the pipe (i.e. the output from the
first \cmdname{cat}) and sends its output to the file \fname{fred2}. (How many
other ways can you think of to do this?) This isn't a very sensible
thing to do, but it does illustrate the principle of piping, and more realistic examples
will appear in the exercises.
Standard output sent to the screen may come so fast that it
disappears off the top before you have had a chance to read it.
There is a simple way around this problem by piping the output into the command \cmdname{less} which arranges to stop after each pageful (or screenful, or window-ful) of output. For example,
\begin{ttoutenv}
\$ ls -la | less
\end{ttoutenv}
would be a wise precaution if the current working directory held
more than a screenful of entries. When \cmdname{less} has shown you the
first screenful, press the space bar to see the next screenful,
or \ttout{return} to see just the next line. Use \ttout{q} as usual to quit.
%\item
% Without foresight, the output will rush past you at a great rate
% of knots. Press \ctrl{s} to stop it dead in its tracks
% (and \ctrl{q} to set it off again).
% In practice this isn't much use nowadays---in most cases the computer is
% just too fast for the Human to press the keys at the right time.
% \end{itemize}
Now would be a good time to remove all those junk files like \fname{fred1} etc.
Before we leave the subject of pipes we meet two of the less obviously
useful Unix commands, \cmdname{fortune} and \ttout{cowsay}. We met
\cmdname{fortune} briefly in Breakbox~\ref{breakbox:fortune}, try
running it a few times now. (Hope you didn't type the command more
than once. If you did, think how that could have been avoided.)
Now try running the command \cmdname{cowsay}. Nothing happens, because
the cow is waiting for you to tell it what to say. Type anything you
like and then \ctrl{d} to denote the end of input. The cow should then
utter your words:
\begin{verbatim}
_____________
< Hello World >
-------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
\end{verbatim}
Now try putting \cmdname{fortune} and \cmdname{cowsay} together to get
the cow to `speak' the fortunes. Utterly useless but it illustrates
the use of pipes.
\subsection{Making your own commands}
\label{sec:making-your-own}
Pretty much anything that you can type at the command line can also be stored in a file to create a simple program called a \concept{shell script}, so if you find yourself frequently connecting together simple commands to perform a particular task, you might find it useful to create a script for use in future, rather than retyping everything each time. If you recall back to Section \ref{section:pipesandredirects} we made a simple command called \texttt{mankyweather} using an \concept{alias}. Aliases are fine for things that you can express in a single line of text, but clumsy for more complex combinations of commands; a shell script instead allows you to use as many lines as you like.
\begin{diversion}{Scripting versus Programming}
You may be wondering what the difference is between a `script' and a `program', or between the idea of `scripting languages' or `programming languages'. It's quite difficult to pin down exact meanings for these, since their use has shifted over time and different people use the terms to mean subtly different things. Scripting languages and programming languages both allow people to create sequences of instructions for a computer to execute. Generally speaking when people refer to scripts or scripting languages they are referring to mechanisms for automating tasks rather than for performing complex computations. So if you wrote something that once a month deleted any files that ended with \fname{.bak} from your filestore, you would probably use a scripting language, and most likely think of it as a script. If you were to write the next 3D blockbuster console game to outsell Grand Theft Auto V, you'd probably use a programming language and think of it as a program. At the extreme ends of the spectrum, the distinction is quite clear; in the middle it gets a bit muddy.
\end{diversion}
Use an editor to create a \concept{shell script} in the file
\ttout{\tilde/bin/wisecow}. Make a directory in your home directory called \fname{bin} using the command:
\begin{ttoutenv}
\$ mkdir \tilde/bin
\end{ttoutenv}
and in that directory create a file called \texttt{wisecow}. You're welcome to use whatever text editor you like for this, but you might find that for short edits like this you're better off using something like \cmdname{nano} rather one of the more heavyweight graphical editors.
Put the following text into the file:
\begin{ttoutenv}
#!/bin/bash
fortune | cowsay
\end{ttoutenv}
The first line tells the operating system to use the program \ttout{/bin/bash}
when this script is run, i.e. it will start \cmdname{bash} with an argument
telling it to get its commands from this file and execute them pretty much as
though they had been typed into bash in the usual way.
Now try to run your new program:
\begin{ttoutenv}
\$ \tilde/bin/wisecow
\end{ttoutenv}
Oops, that won't have worked! Before the operating system will believe us
that this really is a thing that we can run, we need to give the file \concept{execute
permission}. Use \cmdname{ls} to see what permissions the file has at the
moment. To make it \concept{executable} we use \cmdname{chmod} as follows.
\begin{ttoutenv}
\$ chmod +x \tilde/bin/wisecow
\end{ttoutenv}
Now check its permissions again. If all is okay, you should be able to run
this time with
\begin{ttoutenv}
\$ \tilde/bin/wisecow
\end{ttoutenv}
and your wise cow should have spoken.
Now here is the really cool bit: in an earlier lab you met the idea of
\ttout{\$PATH}---the list of all places where the operating system will
search when you type a command without specifying its full pathname. See the
value of this now:
\begin{ttoutenv}
\$ echo \$PATH
\end{ttoutenv}
Notice one of the directories listed is your very own \ttout{\tilde/bin} directory: this
is where you can put \emph{your own} commands.
So, now type just
\begin{ttoutenv}
\$ wisecow
\end{ttoutenv}
and bask in the wisdom of your newly created cow guru.
\subsection{Doing several things at a time: background running}
The command \cmdname{xclock} fires up a clock displaying the current time; try it now.
You will notice that there's a problem with running clocks from a terminal window.
If you type:
\begin{ttoutenv}
\$ xclock\return
\end{ttoutenv}
a clock does indeed appear. However, you then can't type any more
commands in the terminal window, because it is waiting for the
clock program to finish, and of course the clock program is designed
to run forever (or at least until you logout). In this situation you can, of course quit the clock, using \ctrl{c} in the terminal window. However, if you want to keep the clock running and still get on with other things in the same terminal window you can just add an ampersand (\ttout{\&}) on the end of a command, so in this case,
\begin{ttoutenv}
\$ xclock \&
\end{ttoutenv}
Adding the ampersand ensures that the program is run \textbf{in the
background}, that is, separately from the terminal window.
This way you can have several clocks at once and continue typing
other commands carrying on from where you were.
Try running an \ttout{xclock} in the background now.
Work out from the manual page for \ttout{xclock} how to use its various options, and experiment with producing a range of clocks.
(You should ignore the section of the manual page entitled \ttout{X
DEFAULTS} -- for now.)
%Work out the \textbf{command line arguments} needed to make a clock have red hands with blue edges.
One situation where the use of background processes is particularly useful is when you fire up an editor, such as \ttout{gedit}. You can start the editor and still continue to do other things in the same terminal window. Try this now
\begin{ttoutenv}
\$ gedit \&
\end{ttoutenv}
You can also start \ttout{gedit} (and many other editors) with a filename argument to edit a particular file; in fact this is probably the way you will normally use it.
Sometimes you might forget the \ttout{\&} and want to put a process into the background while it is already running. This is easy to do; first you \concept{suspend} the process by typing \ctrl{z}, then type \ttout{bg} to put into the background. Try this now with a \ttout{gedit} window. You can bring a background process back into the foreground by typing \ttout{fg}. If you have more than one suspended or background job then you just add the background process count as an argument; you can find which process has which count by using the shell command \cmdname{jobs}.
% If you have time \emph{later}, try to figure out how to make a clock have a yellow background -- hint: there is only a good clue in the xclock man page, you will need to look at another man page to get the answer.
\subsection{Printing text files: lpr}
The command \cmdname{lpr} can be used to send files to a printer. In its
simplest form, you simply run:
%
\begin{ttoutenv}
\$ lpr file1 file2
\end{ttoutenv}
%
to print the given files. The printing service we use is the University \concept{Pull printing} service, which allows you to collect your printing at \emph{any} University pull printer. This is described in more detail at
{\small
\url{http://www.itservices.manchester.ac.uk/students/printing/}
}
You could use \cmdname{lpr} now to print out the \fname{fortunes}
file, but that file is quite big and we don't want to waste a lot of
paper. So please don't! However, it would be nice to practise using
\cmdname{lpr}. So instead print out just the first 50 lines of
it. Look at the man page for \cmdname{lpr} and discover what it does
if no file names are given. Now look at the man page for the command
\cmdname{head} and figure out how to make it output the first 50 lines
of the file \fname{fortunes}. Experiment with this to make the 50
lines appear on your screen.
% From what you
% have already learnt, you should know how to check there are exactly 50 lines
% using the counting option of \cmdname{cat}.
Now send the 50 lines to the
printer---without using a temporary file. Go and collect your print output
from a nearby printer (there are printers in SSO, G23, and other places).
%
% head -50 fortunes | lpr
\cmdname{lpr} is a basic printing tool for printing text (and it is also
clever enough to print most types of images nowadays). A more sophisticated
printing program is \cmdname{a2ps}. This produces a nicer output, and it
can recognise different types of text file---including program
source code files---and present the various keywords of the programming
language and the program identifiers in different fonts to help with
readability.
Look at the man page for \cmdname{a2ps} and use \cmdname{a2ps} to print the file
\\
\fname{\Dcrsname/SimpleJavaProgram.java}
\\
When you collect
this print output you will see that \cmdname{a2ps} has formatted it nicely. This is a
good way to obtain printouts of your own work, should you wish to.
All students have a printing account which is used to `pay' for their printing. The School has pre-credited your account with enough credit for you to print all the material needed for your courses (with some to spare) without having to pay for anything. For administrative reasons, your initial credit will be \pounds4, and this will be topped-up during the year. The first top-up is likely to occur during Reading Week.
The printing allowance we give you means that you will be able to to print 500 sides during the year if you use the double-sided A4 mono option (at 8p per page). Note: the allowance would only cover 400 sides if you use the A4 single-sided option, at 5p per page, so clearly printing double-sided is your better option.
\begin{firstonly}
\subsection{Time for a checkup}
\label{sec:time-checkup}
\begin{roadblock}{Check your setup}
Now it's time to check that your CS account's environment is set up properly. In the earlier
introductory labs we got you to make various changes to the configuration files that determine how your account behaves (the so-called `dotfiles').
From a terminal, run the command
\begin{ttoutenv}
/opt/teaching/bin/check-my-setup
\end{ttoutenv}
If you skipped any of the steps in the intro labs, or didn't quite get things right, then this script will help you detect any configuration issues that might bite you later, and will help you fix any problems it finds (if you're curious about the script works, use \cmdname{less} to check out its contents).
If you don't understand what the script is telling you to do, please do take this opportunity to find a member of lab staff to explain things.
Once you've fixed any problems that the script has identified, please re-run the script to check everything is now okay, and then repeat this process until the script reports that everything is `good'.
\end{roadblock}
\end{firstonly}
\subsection{Exercises}
Here are a number of exercises to experiment with. Use \cmdname{man}
to find full details of the relevant commands you need to use. When you
have your answers, email them to you personal tutor. Just send a
single email with everything in. If you can't complete all the
exercises, no problem, just send what you've done.
%
\begin{enumerate}
%
%\item Select \fname{File Manager} from \fname{Programs} from the
% workspace menu and explore your filestore visually. Double clicking
% with the left mouse button on an icon opens a file or directory.
%
\item As you know, \ilinput{ls -l} gives you extra information
about files. Skim through the man page for \cmdname{ls} to see what
it means. Check the ownership and permissions of your
own files. For more
about ownership and permissions, look at the manual pages for the
\ttout{chown} and \cmdname{chmod} commands.
\textbf{Question: Why don't you own `..' in your home directory?}
%
\item Look at the \cmdname{man} entry for \cmdname{rm} and find out
what would happen if you did \cmdname{cd} and then
\ilinput{rm -rf * }\\
\textbf{WARNING! DO NOT ACTUALLY TRY THIS!} We once had a system administrator who, after
logging in as the \concept{superuser} (that's a special user called
\concept{root} that has the permission to do \emph{anything}), typed
the above command by accident. What do you think happened? (Hint: on
many Unix systems, the superuser's home directory is \ttout{/}).
\textbf{Question: What would it do in your home directory? What would it do if the
superuser made this error?}
\item Another useful command is \cmdname{grep}, which displays all
lines of a file containing a particular string (in fact, the
string can be a pattern with wild-cards and various other things in).
The form for a simple use of \cmdname{grep} is
\begin{ttoutenv}
grep [PATTERN] [FILENAME(S)]
\end{ttoutenv}
%
This will result in a display of all the lines in the files which
contain the given pattern.
A useful file to use for experiments with \cmdname{grep} is
\fname{/usr/share/dict/words}, which is a spelling dictionary. Try to
find all words
in the dictionary which contain the string `red'.
\textbf{Question: what was the command you used to do this? (Please don't email your
tutor the \emph{results} from the command!)}
\item
Use a suitable pipeline to find out how many
words in the dictionary contain the string `red' but not the
string `fred'. (Hint: The answer to the previous question gives all
the words containing `red', look at the manual page for
\cmdname{grep} to find out how to exclude those words containing
`fred'. The \cmdname{wc} (short for `word count') program counts words
(amongst other things). Use pipes to put them all together.)
\textbf{Question: what was the command you used to do this? How many words did you find?}
% \item Investigate the \cmdname{ps} command, which tells you about the
% processes (running programs) on your workstation, how much swap
% space they are using etc..
% \item (Harder) Wander around the top of the directory tree, from /,
% and try to understand what you find there.
\end{enumerate}
You have now finished the lab, but we encourage you to try the exercises
contained in the file \\\fname{\Dcrsname/extras}. Don't worry if you find them
tricky---they are.
\begin{firstonly}
\subsection{The end of the beginning}
That's it! You've now reached the end of the introductory labs.
What follows next week in your various courses are labs and coursework
that will actually form part of your assessment, and ultimately, your
Degree.
If you're new to Unix/Linux it's a good idea to spend a bit of time
reflecting on and re-reading through what we've already done in order
to ready yourself. Make sure you feel comfortable with the concepts
we've presented. If something seems a little weird, or hard to follow,
spend a bit of time and go over that bit of the lab script
again. Remember, as well as your scheduled class time in the
University, you're expected to also do some work in your private study
time at home.
And most importantly, if you're feeling overwhelmed or even just a
little concerned about your understanding of what you've met so far,
don't worry. Tell us and we'll help. Please don't suffer in
silence---speak to your personal tutor, or email one or all the team
(see below) that created these labs. We're here to help, and we're
very happy to do that. But before we can, you need to tell us! \\
Finally, we want to wish you the best of luck, not just for the coming
weeks, but for the coming semesters and years, in everything you do
here in the School.\\
\\
Steve, Graham, Toby and John.
\vspace{1.5cm}
\begin{table}[h]
\centering
\begin{tabular}{cc}
\includegraphics[width=5cm]{images/srp-mugshot} & \includegraphics[width=5cm]{images/gdg-mugshot} \\
{\small steve.pettifer@manchester.ac.uk} & {\small graham.gough@manchester.ac.uk} \\
\includegraphics[width=5cm]{images/tljh-mugshot} & \includegraphics[width=5cm]{images/jtl-mugshot3.jpg} \\
{\small toby.howard@manchester.ac.uk} & {\small john.latham@manchester.ac.uk} \\
\end{tabular}
\end{table}
\end{firstonly}
\section{Acknowledgements}
These notes are largely our own work, but have been inspired in places by previous lab exercises created by Pete Jinks, John Sargeant and Ian Watson. We're very grateful to Paul Waring, Alex Day, Alex Constantin, Hamza Mahmud and Ben Mulpeter for test driving and debugging the exercises.