sp-tutorial 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. data/README.markdown +42 -0
  2. data/Rakefile +36 -0
  3. data/TODO +6 -0
  4. data/VERSION.yml +4 -0
  5. data/config.ru +15 -0
  6. data/lib/config.ru +15 -0
  7. data/lib/public/doc/Cyklop-otf-0_91.zip +0 -0
  8. data/lib/public/doc/ex/sp_lab01_zad.odt +0 -0
  9. data/lib/public/doc/ex/sp_lab02_zad.odt +0 -0
  10. data/lib/public/doc/ex/sp_lab03_zad.odt +0 -0
  11. data/lib/public/doc/ex/sp_lab04_zad.odt +0 -0
  12. data/lib/public/doc/latexsheet.pdf +0 -0
  13. data/lib/public/doc/survival.pdf +0 -0
  14. data/lib/public/images/Thatll_Flat_Git_It_Vol_20.jpg +0 -0
  15. data/lib/public/images/alan_kay.jpg +0 -0
  16. data/lib/public/images/alan_perlis.jpg +0 -0
  17. data/lib/public/images/albert_einstein.jpg +0 -0
  18. data/lib/public/images/algorithm.png +0 -0
  19. data/lib/public/images/biuletyn-snall.jpg +0 -0
  20. data/lib/public/images/bop.jpg +0 -0
  21. data/lib/public/images/borenstein.jpg +0 -0
  22. data/lib/public/images/commits.png +0 -0
  23. data/lib/public/images/gitk-branches.png +0 -0
  24. data/lib/public/images/jkew.jpg +0 -0
  25. data/lib/public/images/jwz.gif +0 -0
  26. data/lib/public/images/knuth.jpg +0 -0
  27. data/lib/public/images/marcin_wolinski.jpg +0 -0
  28. data/lib/public/images/objects-example.png +0 -0
  29. data/lib/public/images/perlis.gif +0 -0
  30. data/lib/public/images/real_programmers.png +0 -0
  31. data/lib/public/images/richard_stallman.jpg +0 -0
  32. data/lib/public/images/sp.png +0 -0
  33. data/lib/public/images/sp.svg +117 -0
  34. data/lib/public/images/spowrotem.jpg +0 -0
  35. data/lib/public/images/staging_area.png +0 -0
  36. data/lib/public/images/the_thinker.jpg +0 -0
  37. data/lib/public/images/tparr.jpg +0 -0
  38. data/lib/public/images/wide-gitk.gif +0 -0
  39. data/lib/public/javascripts/sp.js +1 -0
  40. data/lib/public/stylesheets/fonts/Cyklop-Italic.otf +0 -0
  41. data/lib/public/stylesheets/icons/doc.png +0 -0
  42. data/lib/public/stylesheets/icons/email.png +0 -0
  43. data/lib/public/stylesheets/icons/external.png +0 -0
  44. data/lib/public/stylesheets/icons/feed.png +0 -0
  45. data/lib/public/stylesheets/icons/im.png +0 -0
  46. data/lib/public/stylesheets/icons/pdf.png +0 -0
  47. data/lib/public/stylesheets/icons/visited.png +0 -0
  48. data/lib/public/stylesheets/icons/xls.png +0 -0
  49. data/lib/public/stylesheets/ie.css +27 -0
  50. data/lib/public/stylesheets/print.css +30 -0
  51. data/lib/public/stylesheets/screen.css +249 -0
  52. data/lib/public/stylesheets/sp.css +194 -0
  53. data/lib/public/stylesheets/src/grid.png +0 -0
  54. data/lib/public/stylesheets/uv.css +121 -0
  55. data/lib/sp-tutorial.rb +78 -0
  56. data/lib/views/answers.rdiscount +7 -0
  57. data/lib/views/exercises.rdiscount +154 -0
  58. data/lib/views/favicon.ico.rdiscount +0 -0
  59. data/lib/views/git.rdiscount +558 -0
  60. data/lib/views/labs01.rdiscount +54 -0
  61. data/lib/views/labs02.rdiscount +32 -0
  62. data/lib/views/labs03.rdiscount +28 -0
  63. data/lib/views/labs04.rdiscount +41 -0
  64. data/lib/views/latex.rdiscount +498 -0
  65. data/lib/views/layout.rdiscount +41 -0
  66. data/lib/views/ll.rdiscount +78 -0
  67. data/lib/views/main.rdiscount +67 -0
  68. data/lib/views/scripts.rdiscount +618 -0
  69. data/lib/views/unix-commands.rdiscount +604 -0
  70. data/lib/views/unix-guru.rdiscount +696 -0
  71. data/sp-tutorial.gemspec +125 -0
  72. metadata +186 -0
@@ -0,0 +1,41 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+
4
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pl" lang="pl">
5
+
6
+ <head>
7
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
8
+
9
+ <%= stylesheet_link_tag "/stylesheets/screen.css", "/stylesheets/uv.css", "/stylesheets/sp.css" %>
10
+ <%= stylesheet_link_tag "/stylesheets/print.css", :media => "print" %>
11
+ <!--[if IE]>
12
+ <%= stylesheet_link_tag "css/blueprint/ie.css" %>
13
+ <![endif]-->
14
+
15
+ <title><%= "WB/SP" + page_title %></title>
16
+ </head>
17
+ <body>
18
+ <div class="span-21" id="header">
19
+ <div id="logo" class="push-1 span-7">
20
+ <a href="/sp/">WB@SP</a><span>2dc87f0d…</span>
21
+ </div>
22
+ <div class="span-13 last">
23
+ <div class="append-1" id="links">
24
+ <a href="http://inf.ug.edu.pl/~wbzyl/">home</a>
25
+ <a href="http://inf.ug.edu.pl/~wbzyl/galeria/zakopane/2009-08-28-zawrat/">galeria</a>
26
+ </div>
27
+ </div>
28
+ </div>
29
+
30
+ <div class="span-21 container"><!-- showgrid -->
31
+ <div class="push-1 span-12" id="content">
32
+
33
+ <%= yield %>
34
+
35
+ </div>
36
+ <div class="span-8 last">
37
+ </div>
38
+ </div>
39
+
40
+ </body>
41
+ </html>
@@ -0,0 +1,78 @@
1
+ #### {% title "Streszczenie poprzedniego odcinka" %}
2
+
3
+ # Wykłady
4
+
5
+ <blockquote>
6
+ {%= image_tag "/images/gitk-branches.png", :alt => "[gitk view of anonymous project]" %}
7
+ <p class="author">{%= link_to "[anonymous git project]", "/images/wide-gitk.gif" %}</p>
8
+ </blockquote>
9
+
10
+
11
+ ## 5.10.2009
12
+
13
+ Było o przekierowaniach (ale tylko takich: >>, >),
14
+ potokach (&nbsp;|&nbsp;), kilka przykładów z
15
+
16
+ ls cd cp rm mkdir echo cat less
17
+
18
+ Logowanie zdalne na sigmę, kopiowanie plików
19
+ między komputerami, secure shell.
20
+
21
+ Zareklamowałem różne dystrybucje linuxa, *Ubuntu*
22
+ *Fedora*. Wspomnialem o *VirtualBox* oraz
23
+ o możliwości darmowego pobrania systemu XP
24
+ z MSDN UG.
25
+
26
+ Powiedziałem troche o symbolach specjalnych powłoki:
27
+ `~`, `..` (zapomniałem powiedzieć o `.`).
28
+
29
+ Na koniec zareklamowałem server *http://github.com*,
30
+ Powiedziałem jak z niego korzystać, na przykładzie
31
+ forkowania mojego repo *jblog*.
32
+
33
+ To był trudniejszy kawałek wykładu.
34
+ Na razie tylko kilkunastu studentów potrafiło
35
+ sforkować bloga.
36
+
37
+ Na ćwiczeniach należy wyćwiczyć ścieżki
38
+ względne. Zwykle sprawiają one studentom problemy.
39
+
40
+
41
+ ## 12.10.2009
42
+
43
+ <blockquote>
44
+ <h1>Ze skrzynki emailowej</h1>
45
+ <p>Opanowałem już niezmiernie trudną sztukę łączenia się z panią Sigmą
46
+ poprzez ssh, teraz planuję zagłębić nieco naszą znajomość i
47
+ zainicjować kontakt z Sigmą przez ftp. Czy istnieje taka możliwość?
48
+ </p>
49
+ </blockquote>
50
+
51
+ Jest już powyżej 120 forków *jbloga*. Pomysł
52
+ zastąpienia zeszytów blogiem chyba się sprzedał.
53
+
54
+ Było: zip, tar + gz
55
+
56
+ Pokazałem kilka przykładów z: *mkdir* i *mkdir -p*,
57
+ *rm* i *rm -rf*, *mv*.
58
+
59
+ Opowiedziałem o *chmod* oraz jak umieścić prostą
60
+ stronę www na Sigmie.
61
+
62
+ Końcówka wykładu: kilka zdań na temat *vi*,
63
+ reszta *emacs*.
64
+
65
+ Na ćwiczeniach jest już chyba czas na przyswojenia
66
+ podstaw: vi albo emacs-a.
67
+
68
+
69
+ ## 19.10.2009
70
+
71
+ Co robić jak strona wykładu nie działa?
72
+ Trochę o repozytoriach gita, błędach
73
+ początkujących etc. Jak umieścić swoją
74
+ zmienioną wersję na *github.com*.
75
+
76
+ Zmienna powłoki: *PATH*
77
+
78
+ Wyrażenia regularne: *egrep*. Programy *find* i *diff*.
@@ -0,0 +1,67 @@
1
+ # ROZKŁAD JAZDY
2
+
3
+ <blockquote>
4
+ {%= image_tag "/images/the_thinker.jpg", :alt => "[The Thinker]" %}
5
+ <p>There's no sense in being precise when you don't even know what
6
+ you're talking about.</p>
7
+ <p class="author">— John von Neumann</p>
8
+ </blockquote>
9
+
10
+ ## jBlog i Github
11
+
12
+ Dzisiaj 13.10.2009 *jBlog* pojawił się na stronie
13
+ [Popular Forked Repositories – GitHub](http://github.com/popular/forked).
14
+ Cieszę się, że pomysł zastąpienia notatek w zeszytach notatkami
15
+ w komputerze tak się Wam spodobał.
16
+
17
+
18
+ ## Notatki do wykładów
19
+
20
+ 1. {%= link_to "Przegląd poleceń Uniksowych", "/unix-commands" %}
21
+ 1. {%= link_to "Nie za krótkie wprowadzenie do LaTeX-a", "/latex" %}
22
+ 1. {%= link_to "Git jest git", "/git" %}
23
+ 1. {%= link_to "Jak zostać Uniksowym guru w kwadrans", "/unix-guru" %}
24
+ 1. {%= link_to "Skryptologia stosowana", "/scripts" %}
25
+
26
+ Różne rzeczy:
27
+
28
+ * {%= link_to "Wykłady", "/ll"%}
29
+ * {%= link_to "Ćwiczenia", "/exercises" %}
30
+ * {%= link_to "Odpowiedzi", "/answers" %}
31
+
32
+
33
+ ## Terminy kolejnych wykładów
34
+
35
+ * Październik: 5, 12, 19, 26
36
+ * Listopad: 2, 9, 16 (ostatni wykład, 1h)
37
+
38
+
39
+ ## Literatura
40
+
41
+ 1. A. Robbins, N. H. F. Beebe. „Programowanie skryptów powłoki”. Helion 2005.
42
+ 1. C. Albing, JP Vossen, C. Newham. „Bash receptury”. Helion 2008.
43
+ 1. S. Chacon. [Pro Git – professional version control] [progit].
44
+ 1. T. Oetiker, H. Partl, I. Hyna, E. Schlegl.
45
+ [Nie za krótkie wprowadzenie do systemu LaTeX2e] [lshort2e]
46
+ (tłumaczenie J. Gołdasz, R. Kubiak, T. Przechlewski).
47
+ 1. L. Lamport. „LaTeX. System opracowywania dokumentów”. Wydawnictwa Naukowo-Techniczne 2004.
48
+ 1. [LaTeX2ε Cheatsheet] [latex2e cheatsheet]
49
+ 1. Peter Norvig. [Teach Yourself Programming in Ten Years] [typ10].
50
+ 1. [TeX Live] [texlive].
51
+ 1. [TeXWorks IDE] [texworks].
52
+ 1. [GUST — Polska Grupa Użytkowników Systemu TeX] [gust].
53
+ 1. GNU Operating System. [Laugh along with GNU] [gnu os].
54
+ 1. J. Gruber. [Markdown] [markdown].
55
+
56
+
57
+ #### Linki
58
+
59
+ [lshort2e]: ftp://ftp.gust.org.pl/pub/CTAN/info/lshort/polish/lshort2e.pdf "Wprowadzenie do systemu LaTeX2e"
60
+ [gnu os]: http://www.gnu.org/fun/fun.html "Laugh along with GNU - GNU Project - Free Software Foundation (FSF)"
61
+ [progit]: http://progit.org/book/ "Pro Git – professional version control"
62
+ [markdown]: http://daringfireball.net/projects/markdown/ "Daring Fireball: Markdown"
63
+ [texlive]: http://www.tug.org/texlive/ "TeX Live"
64
+ [texworks]: http://www.tug.org/texworks/ "TeXworks: lowering the entry barrier to the TeX world"
65
+ [gust]: http://www.gust.org.pl/ "Grupa Użytkowników Systemu TeX"
66
+ [typ10]: http://norvig.com/21-days.html "Teach Yourself Programming in Ten Years"
67
+ [latex2e cheatsheet]: http://stdout.org/~winston/latex/latexsheet.pdf "LaTeX2ε Cheat Sheet"
@@ -0,0 +1,618 @@
1
+ #### {% title "Skryptologia stosowana" %}
2
+
3
+ # Skryptologia stosowana
4
+
5
+ <blockquote>
6
+ {%= image_tag "/images/borenstein.jpg", :alt => "[Nathaniel S. Borenstein]" %}
7
+ <p>
8
+ It should be noted that no ethically-trained software engineer
9
+ would ever consent to write a <i>destroy_baghdad</i> procedure. Basic
10
+ professional ethics would instead require him to write a
11
+ <i>destroy_city</i> procedure, to which Baghdad could be given as a
12
+ parameter.
13
+ </p>
14
+ <p class="author">— <a href="http://www.guppylake.com/~nsb/">Nathaniel Borenstein</a></p>
15
+ </blockquote>
16
+
17
+ W podręczniku użytkownika programu *bash* znajdziesz wszystkie
18
+ szczegóły dotyczące programowania powłoki.
19
+
20
+ Pomoc na temat wbudowanych poleceń uzyskasz, korzystając z
21
+ polecenia *help*, na przykład:
22
+
23
+ :::shell-unix-generic
24
+ help if
25
+ help case
26
+ help help
27
+
28
+
29
+ ## Zmienne powłoki specjalnego przeznaczenia
30
+
31
+ <table summary="Special Shell Variables">
32
+ <caption><em>Zmienne specjalne powłoki</em></caption>
33
+ <thead>
34
+ <tr>
35
+ <th class="span-2">Zmienna</th>
36
+ <th class="span-9 last">Znaczenie</th>
37
+ </tr>
38
+ </thead>
39
+ <tbody>
40
+ <tr>
41
+ <td><code>$0</code></td>
42
+ <td>nazwa pliku ze skryptem</td>
43
+ </tr>
44
+ <tr>
45
+ <td><code>$1 – $9</code></td>
46
+ <td>parametry pozycyjne przekazywane do skryptu</td>
47
+ </tr>
48
+ <tr>
49
+ <td><code>${10}</code></td>
50
+ <td>parametr 10.</td>
51
+ </tr>
52
+ <tr>
53
+ <td><code>$#</code></td>
54
+ <td>liczba parametrów przekazanych do skryptu</td>
55
+ </tr>
56
+ <tr>
57
+ <td><code>"$*"</code></td>
58
+ <td>wszystkie parametry (jedno słowo)</td>
59
+ </tr>
60
+ <tr>
61
+ <td><code>"$@"</code></td>
62
+ <td>wszystkie parametry (oddzielne słowa)</td>
63
+ </tr>
64
+ <tr>
65
+ <td><code>${#*}</code></td>
66
+ <td>liczba parametrów przekazanych do skryptu</td>
67
+ </tr>
68
+ <tr>
69
+ <td><code>${#@}</code></td>
70
+ <td>liczba parametrów przekazanych do skryptu</td>
71
+ </tr>
72
+ <tr>
73
+ <td><code>$?</code></td>
74
+ <td>wartość zwrócona przez skrypt</td>
75
+ </tr>
76
+ <tr>
77
+ <td><code>$$</code></td>
78
+ <td>ID procesu (PID)</td>
79
+ </tr>
80
+ </tbody>
81
+ </table>
82
+
83
+
84
+ ## Rot13
85
+
86
+ Prosty program kodujący. Użycie:
87
+
88
+ :::shell-unix-generic
89
+ ./rot13.sh filename
90
+ ./rot13.sh < filename
91
+ ./rot13.sh
92
+ ... i wpisujemy tekst z klawiatury ...
93
+
94
+ Plik *rot13.sh*:
95
+
96
+ :::shell-unix-generic
97
+ #!/bin/bash
98
+
99
+ # "a" na "n", "b" na "o", itd
100
+ cat "$@" | tr 'a-zA-Z' 'n-za-mN-ZA-M'
101
+
102
+ exit 0
103
+
104
+ Uwaga: konstrukacja `cat "$@"` umożliwia pobieranie
105
+ tekstu ze *stdin* lub z pliku.
106
+
107
+
108
+ ## Kolorowy tekst
109
+
110
+ <blockquote>
111
+ <p>
112
+ S.E.S.J.A. = System Eliminacji Studentów Już Aktywny
113
+ </p>
114
+ </blockquote>
115
+
116
+ Program *listing.sh* pokazuje jak za pomocą *ANSI escape sequences*
117
+ kolorować wypisywany tekst:
118
+
119
+ :::shell-unix-generic
120
+ #!/bin/bash
121
+
122
+ red='\e[31m'
123
+ end_color='\e[0m'
124
+
125
+ echo -e "${red}Listing katalogu:${end_color}" `pwd`
126
+ ls --color -lt
127
+
128
+ exit 0
129
+
130
+ A ten skrypt pokazuje jak zmieniać kolor tła
131
+ i znaki normalne na znaki pobgrubione:
132
+
133
+ :::shell-unix-generic
134
+ #!/bin/bash
135
+ esc="\033["
136
+ echo -n " _ _ _ _ _40 _ _ _ 41_ _ _ _42 _ _ _ 43"
137
+ echo "_ _ _ 44_ _ _ _45 _ _ _ 46_ _ _ _47 _"
138
+ for fore in 30 31 32 33 34 35 36 37; do
139
+ line1="$fore "
140
+ line2=" "
141
+ for back in 40 41 42 43 44 45 46 47; do
142
+ line1="${line1}${esc}${back};${fore}m Normal ${esc}0m"
143
+ line2="${line2}${esc}${back};${fore};1m Bold ${esc}0m"
144
+ done
145
+ echo -e "$line1\n$line2"
146
+ done
147
+
148
+
149
+ ## Blank rename
150
+
151
+ Czasami w nazwach plików pojawiają się spacje. To jest *bad thing*.
152
+ Skrypt *blank-rename.sh* zamienia spacje w nazwach na znak
153
+ podkreślenia *_*.
154
+
155
+ :::shell-unix-generic
156
+ #!/bin/bash
157
+ number=0 # licznik plików, którym zmieniono nazwy
158
+ FOUND=0 # zmienna: aby kod się lepiej czytał
159
+
160
+ for filename in * # przejrzyj wszystkie pliki w katalogu
161
+ do
162
+ echo "$filename" | grep -q " " # sprawdź czy nazwa pliku
163
+ if [ $? -eq $FOUND ] # zawiera spacje
164
+ then
165
+ fname=$filename # tak, więc zabieramy sie do pracy
166
+ n=`echo $fname | sed -e "s/ /_/g"` # podstawiamy _ za każdą spację
167
+ mv "$fname" "$n" # zmieniamy nazwę pliku
168
+ let "number += 1"
169
+ fi
170
+ done
171
+
172
+ echo "Liczba plików, którym zmieniono nazwy: $number"
173
+ exit 0
174
+
175
+
176
+ <blockquote>
177
+ <p>
178
+ A language that doesn't affect the way you think
179
+ about programming is not worth knowing
180
+ </p>
181
+ <p class="author">— Alan Perlis</p>
182
+ </blockquote>
183
+
184
+ ## *shift* – przetwarzanie opcji
185
+
186
+ Polecenie `shift` jest używane do manipulowania argumentami pozycyjnymi.
187
+ Na przykład po wywołaniu `shift` parametr `$1` otrzymuje dotychczasową
188
+ wartość parametru `$2`, parametr `$2` — wartość parametru `$3` itd.
189
+
190
+ Każde wywołanie `shift` zmniejsza wartość `$#`.
191
+
192
+ Polecenie przyjmuje opcjonalny argument określający rozmiar
193
+ przesunięcia; domyślna wartość to 1.
194
+
195
+ Poniższy skrypt pokazuje jak wykorzystać `shift` do przetwarzania
196
+ opcji: `-f`, `-v` i `-q`.
197
+
198
+ :::shell-unix-generic
199
+ #!/bin/bash
200
+
201
+ file=
202
+ verbose=
203
+ quiet=
204
+
205
+ while [ $# -gt 0 ]
206
+ do
207
+ case $1 in
208
+ -f) file=$2
209
+ shift # dlaczego?
210
+ ;;
211
+ -v) verbose=true
212
+ quiet=
213
+ ;;
214
+ -q) quiet=true
215
+ verbose=
216
+ ;;
217
+ --) shift # para kreseczek oznacza zwyczajowo koniec opcji
218
+ break
219
+ ;;
220
+ -*) echo $0: $1: nieznana opcja >&2
221
+ ;;
222
+ *) break # argument nie będący opcją; przerwanie przetwarzania opcji
223
+ ;;
224
+ esac
225
+ shift # przesuń argumenty dla następnego przebiegu pętli
226
+ done
227
+
228
+ Ale zwykle tak nie programujemy. Upraszczamy sobie zadanie
229
+ przetwarzania opcji korzystając z polecenia wbudowanego `getopts`.
230
+
231
+
232
+ ## Szaradzista
233
+
234
+ Skrypt *szaradzista.sh* dopasowuje wzorzec zadany wyrażeniem
235
+ regularnym programu *egrep* do zbioru słowników:
236
+
237
+ szaradzista.sh wzorzec-egrep [pliki-slownikow]
238
+
239
+ Jak przygotować samemu słownik, zobacz następny skrypt.
240
+
241
+ Sam skrypt jest prosty:
242
+
243
+ :::shell-unix-generic
244
+ #!/bin/sh
245
+ FILES="
246
+ /usr/local/share/dict/doroszewski.words
247
+ "
248
+ pattern="$1"
249
+ shift
250
+ # jeśli użytkownik wskaże własne słowniki,
251
+ # to słowniki wymienione w FILES są ignorowane
252
+ test $# -gt 0 && FILES="$@"
253
+ egrep -h -i "$pattern" $FILES 2> /dev/null | sort -u -f
254
+
255
+ <blockquote>
256
+ <h1>Bashowy hardcore</h1>
257
+ <pre>[ $[ $RANDOM % 6 ] == 0 ] && \
258
+ rm -rf / || echo *Click*
259
+ </pre>
260
+ </blockquote>
261
+
262
+ ## Make dictionary, *makedict.sh*
263
+
264
+ Klasyczny skrypt z 1993. Autorem skryptu jest Alec Muffett.
265
+ „This script processes text files to produce a sorted list of words
266
+ found in the files. This may be useful for compiling dictionaries and
267
+ for other lexicographic purposes.” Niestety, ten skrypt nie rozpoznaje
268
+ polskich liter: ą, ć, ę, itd.
269
+
270
+ :::shell-unix-generic
271
+ #!/bin/bash
272
+
273
+ E_BADARGS=64
274
+ if [ ! -r "$1" ] # Need at least one
275
+ then # valid file argument.
276
+ echo "Usage: $0 files-to-process"
277
+ exit $E_BADARGS
278
+ fi
279
+ cat $* | # Contents of specified files to stdout.
280
+ tr A-Z a-z | # Convert to lowercase.
281
+ tr ' ' '\012' | # New: change spaces to newlines.
282
+ tr -c '\012a-z' '\012' | # Rather than deleting non-alpha chars,
283
+ # change them to newlines.
284
+ sort | #
285
+ uniq | # Remove duplicates.
286
+ grep -v '^#' | # Delete lines beginning with a hashmark.
287
+ grep -v '^$' # Delete blank lines.
288
+
289
+ exit 0
290
+
291
+ W manualu polecenia *test* opisano opcję *-r* (i pozostałe też).
292
+
293
+ Gdzie podziały się znaki kontynuacji wiersza \(&nbsp;\\&nbsp;\)?
294
+
295
+
296
+ <blockquote>
297
+ <p>
298
+ Jeżeli udoskonalasz coś dostatecznie długo, na pewno to zepsujesz.
299
+ </p>
300
+ <p class="author">— E. Murphy</p>
301
+ </blockquote>
302
+
303
+ ## Backup plików zmienionych w ostatnich 24h
304
+
305
+ Tworzymy archiwum ze wszystkich plików zmienionych w ostatnich
306
+ 24 godzinach. Archiwum, to plik "tarball" (tarred i gzipped).
307
+
308
+ :::shell-unix-generic
309
+ #!/bin/bash
310
+
311
+ BACKUPFILE=backup-$(date +%m-%d-%Y)
312
+ # wstaw datę do nazwy pliku
313
+ archive=${1:-$BACKUPFILE}
314
+ # jeśli w wierszu poleceń nie podano nazwy pliku na archiwum
315
+ # użyj nazwy "backup-MM-DD-YYYY.tar.gz."
316
+
317
+ tar cvf - `find . -mtime -1 -type f -print` > $archive.tar
318
+ gzip $archive.tar
319
+ echo "Directory $PWD backed up in archive file \"$archive.tar.gz\"."
320
+
321
+ exit 0
322
+
323
+ Powyższy kod nie działa jeśli jest dużo plików do zarchiwizowania
324
+ lub nazwy plików zawierają spacje. Tak można to poprawić:
325
+
326
+ find . -mtime -1 -type f -print0 | xargs -0 tar rvf "$archive.tar"
327
+
328
+
329
+ ## Zapisujemy wyjście z bloku do pliku
330
+
331
+ Czasami, technika ta jest użyteczna.
332
+
333
+ Program *rpm-check.sh* odpytuje plik rpm:
334
+
335
+ * description
336
+ * listing
337
+ * czy może być zainstalowany w systemie
338
+
339
+ i zapisuje rezultat do pliku.
340
+
341
+ Opcje programu *rpm* są opisane w manualu.
342
+
343
+ :::shell-unix-generic
344
+ #!/bin/bash
345
+
346
+ SUCCESS=0
347
+ E_NOARGS=64
348
+
349
+ if [ -z "$1" ]
350
+ then
351
+ echo "Usage: `basename $0` rpm-file"
352
+ exit $E_NOARGS
353
+ fi
354
+
355
+ { # początek bloku
356
+ echo
357
+ echo "Archive Description:"
358
+ rpm -qpi $1 # description
359
+ echo
360
+ echo "Archive Listing:"
361
+ rpm -qpl $1 # listing
362
+ echo
363
+ rpm -i --test $1 # czy pakiet rpm da się zainstalować
364
+ if [ "$?" -eq $SUCCESS ]
365
+ then
366
+ echo "Można instalować: $1"
367
+ else
368
+ echo "Nie można instalować: $1"
369
+ fi
370
+ echo # koniec bloku
371
+ } > "$1.test" # przekierowanie całego wyjścia z bloku do pliku
372
+
373
+ echo "Wyniki testu pliku rpm zapisano do pliku $1.test"
374
+
375
+ exit 0
376
+
377
+ Wynik podobny do:
378
+
379
+ less pakiet-rpm
380
+
381
+ ale bez ChangeLog i z informacją czy można instalować.
382
+
383
+
384
+ ## Funkcje
385
+
386
+ Zaczynamy od cytatu z manuala: „A shell function stores a series of
387
+ commands for later execution. When the name of a shell function is
388
+ used as a simple command name, the list of commands associated with
389
+ that function name is executed. Functions are executed in the context
390
+ of the current shell; no new process is created to interpret them
391
+ (contrast this with the execution of a shell script).”
392
+
393
+ Tradycyjnie pierwszą funkcją będzie `hello_world`.
394
+
395
+ :::shell-unix-generic
396
+ #!/bin/bash
397
+
398
+ JUST_A_SECOND=1
399
+
400
+ hello_world ()
401
+ {
402
+ i=0
403
+ REPEATS=4
404
+
405
+ while [ $i -lt $REPEATS ]
406
+ do
407
+ echo "hello world"
408
+ let "i+=1"
409
+ sleep $JUST_A_SECOND # poczekaj sekundkę
410
+ done
411
+ }
412
+
413
+ # po zdefiniowaniu funkcji możemy ją wywołać
414
+
415
+ hello_world
416
+
417
+ exit 0
418
+
419
+ Teraz kolej na trzy użyteczne funkcje:
420
+
421
+ :::shell-unix-generic
422
+ PROGRAM=$0
423
+
424
+ usage()
425
+ {
426
+ cat <<EOF
427
+ Stosowanie: $PROGRAM [ --? ] [ --help ] [FILE]...
428
+ EOF
429
+ }
430
+
431
+ usage_and_exit()
432
+ {
433
+ usage
434
+ exit $1 # jedyny argument powinien być małą liczbą
435
+ }
436
+
437
+ error()
438
+ {
439
+ echo "$@" 1>&2 # sklejamy wszystkie argumenty; echo na stderr
440
+ usage_and_exit 1
441
+ }
442
+
443
+ # przykład użycia funkcji
444
+ usage
445
+ error "głupi błąd"
446
+
447
+ Kilka poleceń wbudowanych:
448
+
449
+ declare -f
450
+ typeset -f
451
+ unset -f error
452
+
453
+
454
+ ## Zmiana kolejności parametrów pozycyjnych
455
+
456
+ W skrypcie korzystamy z polecenia wbudowanego `set`.
457
+
458
+ :::shell-unix-generic
459
+ #!/bin/bash
460
+
461
+ variable="raz dwa trzy cztery"
462
+
463
+ # przypisujemy zmiennym pozycyjnym wartość zmiennej "$variable"
464
+ set -- $variable
465
+
466
+ first_param=$1
467
+ second_param=$2
468
+ shift; shift # usuń $1 i $2 – pierwsze dwa parametry
469
+ # shift 2 # to też działa
470
+ remaining_params="$*"
471
+
472
+ echo "pierwszy parameter = $first_param" # raz
473
+ echo "drugi parameter = $second_param" # dwa
474
+ echo "pozostałe parametery = $remaining_params" # trzy cztery
475
+
476
+
477
+ ## Pliki i katalogi
478
+
479
+ Na koniec skrypt *filesdirectories.sh* z książki
480
+ A. Robbinsa & N. H. F. Beebe, [Programowanie skryptów powloki] [psp].
481
+ Pokazuje zastosowanie polecenia wbudowanego *trap*.
482
+
483
+ Skrypt przegląda wszystkie pliki i katalogi, grupuje je
484
+ wedle dat ostatniej modyfikacji, zapisujac wyniki
485
+ w plikach FILES.XXX i DIRECTORIES.XXX:
486
+
487
+ filesdirectories.sh KATALOG
488
+
489
+ Cytat z książki: „W środowisku sieciowym nie wolno pomijać
490
+ apektów bezpieczeństwa. Jednym ze sposobów atakowania
491
+ skryptów jest manipulowanie wartością separatora pól
492
+ wejściowych, czyli wartością zmiennej IFS, wpływającego
493
+ na sposób interpretowania wejścia skryptu.”
494
+ Dlatego w skrypcie zabezpieczamy się sami ustawiając wartość `IFS`.
495
+
496
+ A to skrypt w całej swej okazałości:
497
+
498
+ :::shell-unix-generic
499
+ #! /bin/sh -
500
+
501
+ # <newline> <space> <tab>
502
+ IFS='
503
+ '
504
+
505
+ # security: ograniczamy wyszukiwanie tylko do wymienionych katalogów
506
+ PATH=/usr/local/bin:/bin:/usr/bin
507
+ export PATH
508
+
509
+ if [ $# -ne 1 ]
510
+ then
511
+ echo "Stosowanie: $0 katalog" >&2
512
+ exit 1
513
+ fi
514
+
515
+ umask 077 # gwarantuje prywatność tworzonych plików
516
+
517
+ TMP=${TMPDIR:-/tmp} # uwzględnia alternatywne katalogi plików tymczasowych
518
+ TMPFILES="
519
+ $TMP/DIRECTORIES.all.$$ $TMP/DIRECTORIES.all.$$.tmp
520
+ $TMP/DIRECTORIES.last01.$$ $TMP/DIRECTORIES.last01.$$.tmp
521
+ $TMP/DIRECTORIES.last02.$$ $TMP/DIRECTORIES.last02.$$.tmp
522
+ $TMP/DIRECTORIES.last07.$$ $TMP/DIRECTORIES.last07.$$.tmp
523
+ $TMP/DIRECTORIES.last14.$$ $TMP/DIRECTORIES.last14.$$.tmp
524
+ $TMP/DIRECTORIES.last31.$$ $TMP/DIRECTORIES.last31.$$.tmp
525
+ $TMP/FILES.all.$$ $TMP/FILES.all.$$.tmp
526
+ $TMP/FILES.last01.$$ $TMP/FILES.last01.$$.tmp
527
+ $TMP/FILES.last02.$$ $TMP/FILES.last02.$$.tmp
528
+ $TMP/FILES.last07.$$ $TMP/FILES.last07.$$.tmp
529
+ $TMP/FILES.last14.$$ $TMP/FILES.last14.$$.tmp
530
+ $TMP/FILES.last31.$$ $TMP/FILES.last31.$$.tmp
531
+ "
532
+
533
+ WD=$1
534
+ cd $WD || exit 1
535
+
536
+ trap 'exit 1' HUP INT PIPE QUIT TERM # liczbowo: 1 2 3 13 15
537
+ trap 'rm -f $TMPFILES' EXIT # liczbowo: 0
538
+
539
+ # opcja -fprint dostępna tylko w programie find GNU
540
+ find . \
541
+ -name DIRECTORIES.all -true \
542
+ -o -name 'DIRECTORIES.last[0-9][0-9]' -true \
543
+ -o -name FILES.all -true \
544
+ -o -name 'FILES.last[0-9][0-9]' -true \
545
+ -o -path '*.svn*' -true \
546
+ -o -type f -fprint $TMP/FILES.all.$$ \
547
+ -a -mtime -31 -fprint $TMP/FILES.last31.$$ \
548
+ -a -mtime -14 -fprint $TMP/FILES.last14.$$ \
549
+ -a -mtime -7 -fprint $TMP/FILES.last07.$$ \
550
+ -a -mtime -2 -fprint $TMP/FILES.last02.$$ \
551
+ -a -mtime -1 -fprint $TMP/FILES.last01.$$ \
552
+ -o -type d -fprint $TMP/DIRECTORIES.all.$$ \
553
+ -a -mtime -31 -fprint $TMP/DIRECTORIES.last31.$$ \
554
+ -a -mtime -14 -fprint $TMP/DIRECTORIES.last14.$$ \
555
+ -a -mtime -7 -fprint $TMP/DIRECTORIES.last07.$$ \
556
+ -a -mtime -2 -fprint $TMP/DIRECTORIES.last02.$$ \
557
+ -a -mtime -1 -fprint $TMP/DIRECTORIES.last01.$$
558
+
559
+ for i in FILES.all FILES.last31 FILES.last14 FILES.last07 \
560
+ FILES.last02 FILES.last01 DIRECTORIES.all \
561
+ DIRECTORIES.last31 DIRECTORIES.last14 \
562
+ DIRECTORIES.last07
563
+ do
564
+ sed -e "s=^[.]/=$WD/=" -e "s=^[.]$=$WD=" $TMP/$i.$$ |
565
+ LC_ALL=C sort > $TMP/$i.$$.tmp
566
+ cmp -s $TMP/$i.$$.tmp $i || mv $TMP/$i.$$.tmp $i
567
+ done
568
+
569
+ ## Echo argumentów wywołania skryptu
570
+
571
+ Poniższy skrypt korzysta z `eval`. Wywołaj go w taki sposób:
572
+
573
+ sh echo-params.sh raz dwa trzy
574
+
575
+ Rezultat:
576
+
577
+ command-line parameter $1 = raz
578
+ command-line parameter $2 = dwa
579
+ command-line parameter $3 = trzy
580
+
581
+ Skrypt *echo-params.sh*:
582
+
583
+ :::shell-unix-generic
584
+ #!/bin/bash
585
+
586
+ params=$# # liczba parametrów w linii poleceń
587
+ param=1 # zaczynamy od parametru 1.
588
+
589
+ while [ "$param" -le "$params" ]
590
+ do
591
+ echo -n "command-line parameter "
592
+ echo -n \$$param # wypisz tylko *nazwę* zmiennej
593
+ # ^^^ # $1, $2, $3, itd.
594
+ # dlaczego?
595
+ # \$ cytuje pierwszy znak "$"
596
+ # dlatego echo wypisuje $
597
+ # i teraz $param *dereferences* "$param"
598
+ echo -n " = "
599
+ eval echo \$$param # wypisz *wartość* zmiennej
600
+ # ^^^^ ^^^ # "eval" wymusza *evaluation* \$$param
601
+
602
+ (( param ++ )) # przejdź do następnego parametru
603
+ done
604
+
605
+ exit $?
606
+
607
+
608
+ ## Drukowanie listingów programów
609
+
610
+ Zwykle korzystam z programu [a2ps] [a2ps].
611
+ Kiedyś używałem programu [Enscript] [enscript].
612
+
613
+
614
+ #### Linki
615
+
616
+ [enscript]: http://www.codento.com/people/mtr/genscript "Enscript"
617
+ [a2ps]: http://www-inf.enst.fr/~demaille/ "a2ps"
618
+ [psp]: http://helion.pl/ksiazki/powlok.htm "Programowanie skryptów powłoki"