-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.html
789 lines (689 loc) · 31.5 KB
/
index.html
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
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>The CLUI</title>
<meta name="description" content="Get your CLUI on.">
<meta name="author" content="Brian Dailey">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="css/reveal.min.css">
<link rel="stylesheet" href="css/theme/default.css" id="theme">
<!-- For syntax highlighting -->
<link rel="stylesheet" href="lib/css/zenburn.css">
<!-- If the query includes 'print-pdf', include the PDF print sheet -->
<script>
if( window.location.search.match( /print-pdf/gi ) ) {
var link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = 'css/print/pdf.css';
document.getElementsByTagName( 'head' )[0].appendChild( link );
}
</script>
<style>
div#notes { font-size: 80%; }</style>
<!--[if lt IE 9]>
<script src="lib/js/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<div class="reveal">
<!-- Any section element inside of this container is displayed as a slide -->
<div class="slides">
<section>
<h1>Command Line Kung Fu</h1>
<h3>The shell, and why <br/>you should care</h3>
<p>
Brian Dailey (@byeliad)
</p>
<p><small>(Pess "s" for speaker notes.)</small></p>
<aside class="notes">
Hi! My name is Brian Dailey. This is a talk about the Unix shell
environment. What it is, why you should know it, and some helpful
tips and tricks to get you going.
CLI is seeing more use compared to 5 years prior, especially BSD-based
Mac OS X. Hopefully even if you're wizened, you'll learn some new tricks.
My background started in MS-DOS 5.0 in 1995. Didn't like Win95.
Introduced to Redhat 7.2 in 2001, Knoppix, DSL.
2006 and on, Ubuntu. 2012, Mac reluctantly embraced.
</aside>
</section>
<section>
<h2>The Shell</h2>
<p>
Evolved from a text only environment.
</p>
<aside class="notes">
* If you don't know what the shell is at all, it's
* a way to interface with computers that involves only a keyboard.
* existed prior to the WIMP interface we know today.
* evolved from typewriters connected to line printers.
</aside>
</section>
<section>
<div style="text-align: left;">
<code data-trim>
$ <span class="fragment">input</span>
<br/>
<span class="fragment">output</span>
<br/>
<span class="fragment">$ input</span>
<br/>
<span class="fragment">output</span>
</code>
</div>
<aside class="notes">
When you start a shell, usually you'll see a simple text prompt and little else.
It may seem intimidating, but fundamentally it's just a machine that accepts input
and accepts output. It may do it a little differently than you're used to.
</aside>
</section>
<section>
<h3>You
<br/>
▲<br/>
▼
<span class="fragment">
<br/>
Shell
<br/>
▲<br/>
▼
</span>
<br/>
Computer
</h3>
<aside class="notes">
You can think of the shell as a layer that sits between you and the computer
</aside>
</section>
<section>
<h2>It's A Little Terse</h2>
<pre><code>1 tr -cs A-Za-z '\n' |
2 tr A-Z a-z |
3 sort |
4 uniq -c |
5 sort -rn |
6 sed ${1}q
</code></pre>
<h2 class="fragment">Some might say "Cryptic"</h2>
</section>
<section>
<h3>To the unitiated, it might seem..</h3>
<p class="fragment">An enigma...</p>
<p class="fragment">Wrapped in a mystery.</p>
</section>
<section>
<img src="img/chupacabra_s.jpg" alt="chupacabra" />
<h3>Swallowed by a Chupacabra</h3>
</section>
<section>
<img src="img/deep_crow_s.jpg" alt="deep crow" />
<h3>Eaten by a Deep Crow</h3>
</section>
<section>
<img src="img/cthulhu_s.jpg" alt="cthulhu" />
<h3>Consumed by Cthulhu</h3>
</section>
<section>
<p>However, once you spend some time with it,
<br/>
you'll see it's not really all that scary.</p>
</section>
<section>
<p>You need not look like a wizard to be a CLUI wizard.</p>
<img src="img/ken_n_dennis.jpg" alt="ken_n_dennis" />
<aside class="notes">
This is Ken Thompson and Dennis Ritchie, two
developers of Unix and evangelists of the Unix philosophy.
</aside>
</section>
<section>
<p>So let's talk about what makes it worth your time.</p>
</section>
<section>
<h2>Unix Philosophy</h2>
<aside class="notes">
Cobbed together over time by the core developers
of the Unix operating system as well as those writing
some of it's most commonly used tools.
</aside>
</section>
<section>
<p><q>
"Although [this] philosophy can't be written down in a single sentence, at its heart is the idea that the power of a system comes more from the relationships among programs than from the programs themselves. Many UNIX programs do quite trivial things in isolation, but, combined with other programs, become general and useful tools."
</q>
<br/>
<br/>
— <u>The Unix Programming Environment</u></p>
<aside class="notes">
In their preface to the 1984 book, The UNIX Programming Environment, Brian Kernighan and Rob Pike, both from Bell Labs, give a brief description of the Unix design and the Unix philosophy...
Now he said we can't summarize it in one sentence, but the key
takeaway for this talk is...
</aside>
</section>
<section>
<h3>Relationships > Programs</h3>
<aside class="notes">
"...simplicity of both the interface and the
implementation are more important than any other
attributes of the system—including correctness, consistency,
and completeness."
To sum it up even further...
</aside>
</section>
<section>
<h1>Modularity</h1>
<aside class="notes">
Components that can be arranged in many different ways.
</aside>
</section>
<section>
<img src="img/mcilroy.jpg" alt="McIlroy" />
<h3>4 Tenets</h3>
<aside class="notes">
* This dapper lad is Doug McIlroy. He is the inventor of pipes, which we'll talk about shorlty.
* Some say this guy can read data from /dev/null
* In 1984, the Department of Justice broke up AT&T because they had a monopoly. On Doug McIlroy.
* He wrote three guiding principles for the Unix philosophy.
</aside>
</section>
<section><h1>1.</h1></section>
<section>
<p>Make each program do one thing well. To do a new job, build afresh rather than complicate old programs by adding new features.</p>
<aside class="notes">Modularity - composability - "components that can be selected and assembled in various combinations to satisfy specific user requirements." </aside>
</section>
<section><h1>2.</h1></section>
<section>
<p>Expect the output of every program to become the input to another, as yet unknown, program. Don't clutter output with extraneous information. Avoid stringently columnar or binary input formats. Don't insist on interactive input.</p>
<aside class="notes">
Second, the ability to take the output of one and put it into another. Don't expect interactive input.
</aside>
</section>
<section><h1>3.</h1></section>
<section>
<p> Design and build software, even operating systems, to be tried early, ideally within weeks. Don't hesitate to throw away the clumsy parts and rebuild them.</p>
<aside class="notes">Strike forward, but don't be afraid to abandon dead end trails!</aside>
</section>
<section><h1>4.</h1></section>
<section>
<p> Use tools in preference to unskilled help to lighten a programming task, even if you have to detour to build the tools and expect to throw some of them out after you've finished using them. </p>
<aside class="notes">Don't throw bodies at a problem that can be scripted.</aside>
</section>
<section>
<h3>So what does all of this mean for me?</h3>
</section>
<section>
<h4>Every *nix tool you learn multiplies the<br/> usefulness of the ones you already know.</h4>
</section>
<section data-background="img/whoa.jpg">
<aside class="notes">I don't know about you, but... whoa.</aside>
</section>
<section>
<p><q>"Read a file of text, determine the n most frequently used words, and print out a sorted list of those words along with their frequencies."</q></p>
<aside class="notes">
This was a 'problem' posed for Donald Knuth to answer to demonstrate literate
programming. McIlroy was asked to write a literary style critique of it.
Knuth's solution was presented lucidly, but it was 10+ pages long.
He started out by appreciating the presentation and cleverness of the data structure, but then he dropped this...
</aside>
</section>
<section>
<pre><code>1 tr -cs A-Za-z '\n' |
2 tr A-Z a-z |
3 sort |
4 uniq -c |
5 sort -rn |
6 sed ${1}q
</code></pre>
</section>
<section>
<p><q>"If you are not a UNIX adept, you may need a little explanation, but not much, to understand this pipeline of processes. The plan is easy:"</q></p>
</section>
<section>
<pre><code>1 tr -cs A-Za-z '\n' |
2 tr A-Z a-z |
3 sort |
</code></pre>
<ul>
<li>Make one-word lines by transliterating the complement (-c) of the alphabet into newlines (note the quoted newline), and squeezing out (-s) multiple newlines.</li>
<li>Transliterate upper case to lower case.</li>
<li>Sort to bring identical words together.</li>
</ul>
</section>
<section>
<pre><code>4 uniq -c |
5 sort -rn |
6 sed ${1}q
</code></pre>
<ul>
<li>Replace each run of duplicate words with a single representative and include a count (-c).</li>
<li>Sort in reverse (-r) numeric (-n) order.</li>
<li>Pass through a stream editor; quit (q) after printing the number of lines designated by the script’s first parameter (${1}).</li>
</ul>
</section>
<section data-background="img/mind-blown.gif">
</section>
<section>
<h3>More reasons...</h3>
<aside class="notes>">
<ul>
<li>You're probably already using it.</li>
<li>You'll be able to work from nearly any *nix based platform.</li>
<li>Huge set of tools already exists to make your life easier.</li>
</ul>
</aside>
</section>
<section>
<h3>Reason's not to...</h3>
</section>
<section>
<img src="img/huge_mistake.jpg" alt="mistake" />
<aside class="notes">
The learning curve might seem a little steep at first.
It seems intimidating, but it isn't.
</aside>
</section>
<section>
<h2>Advanced Beginner,</h2>
<h2>Competent,</h2>
<h2>Or Proficient?</h2>
<aside class="notes">
A lot of us may edge into the advanced beginner or competent
but the sweet spot is proficient. That's where I want to be.
I'm too dumb to be an expert, but you can aim for that.
</aside>
</section>
<section>
<h3>So where do I start?</h3>
</section>
<section>
<ul>
<li>Amazon EC2 instance w/ Ubuntu</li>
<li>Ubuntu Live CD</li>
<li>Mac OS X + homebrew</li>
<li>Cygwin (if you must)</li>
</ul>
</section>
<section>
<h1>Getting Around</h1>
<aside class="notes">
One of the first frustrations I see with shell
inductees is getting around without a mouse.
Moving the cursor around is not intuitive.
</aside>
</section>
<section>
<p>Moving the cursor:</p>
<pre> Ctrl + a Go to the beginning of the line (Home)
Ctrl + e Go to the End of the line (End)
Ctrl + p Previous command (Up arrow)
Ctrl + n Next command (Down arrow)
Alt + b Back (left) one word
Alt + f Forward (right) one word
Ctrl + f Forward one character
Ctrl + b Backward one character
Ctrl + xx Toggle between the start of line and current cursor position</pre>
</section>
<section>
<p>Editing:</p>
<pre> Ctrl + L Clear the Screen, similar to the clear command
Ctrl + u Cut/delete the line before the cursor position.
Alt + Del Delete the Word before the cursor.
Alt + d Delete the Word after the cursor.
Ctrl + d Delete character under the cursor
Ctrl + h Delete character before the cursor (backspace)
Ctrl + w Cut the Word before the cursor to the clipboard.
Ctrl + k Cut the Line after the cursor to the clipboard.
Alt + t Swap current word with previous
Ctrl + t Swap the last two characters before the cursor (typo).
Esc + t Swap the last two words before the cursor.
ctrl + y Paste the last thing to be cut (yank)
Alt + r Cancel the changes and put back the line as it was in the history (revert).
ctrl + _ Undo
</pre>
</section>
<section>
<img src="img/mac_esc_key.png" alt="mac esc" />
</section>
<section>
<h1>Shell it Live!</h1>
<h3>Hope I don't screw it up!</h3>
</section>
<section>
<h3>Where do all of these shortcuts come from?</h3>
</section>
<section>
<h1>GNU Readline Library</h1>
<aside class="notes">
Comes in emacs and vim mode flavors.
I didn't discover vim mode before it was too late. emacs is default.
Congrats, you are now an emacs wizard! Better insure your wrists.
Beauty is that these are consistently available in many places:
MySQL, Postgres, Python REPL, Ruby REPL, even PHP Interactive Shell.
</aside>
</section>
<section>
<h3>Things you also get...</h3>
</section>
<section>
<h2>Tab Completion</h2>
<pre>
$ ls Gr[tab]
$ ls Gruntfile.js
$ ls i[tab][tab]
img/ index.html
$ git commit [tab]
$ git commit index.html
</pre>
<aside class="notes">
Auto completes files and directories, and even
arguments to commands.
Can be very clever if you
install some addon packages that
will auto complete hostnames, context-sensitive
arguments, and more.</aside>
</section>
<section>
<h2>GNU History Library</h2>
<pre>
Ctrl + r Search back through history
Ctrl + s Search forward through history
Alt + . Use the last word of the previous command
Ctrl + g Escape from history searching mode
</pre>
</section>
<section>
<h3>On argument reuse...</h3>
</section>
<section>
<pre>
!! Rerun previous command.
!l Rerun previous command starting with 'l'
!l:p Print (don't execute) last command starting with 'l'
!$ Last argument in previous command.
!* All arguments in previous command.
</pre>
</section>
<section>
<h1>Redirecting</h1>
</section>
<section>
<img src="img/stdstreams.svg" alt="std streams" />
<br/>
<a href="http://en.wikipedia.org/wiki/File:Stdstreams-notitle.svg">Source: Wikipedia</a>
<aside class="notes">
The shell introduces the concept of streams.
stdin, stdout, and stderr. Typically, your
keyboard is stdin and your display will receive
stdout and stderr. However, this isn't always the case.
</aside>
</section>
<section>
<h3>stdout to file</h3>
<pre><code class="bash"># sort lines and write to a file
sort myfile.txt > sorted_myfile.txt
# same as above, but append to existing file.
$ sort myfile2.txt >> sorted_myfile.txt
</code></pre>
<aside class="notes">
For starters, you can redir to a file.
In the first example, stdout is redirected to
a file. In the second example, we're doing the
same thing but it appends to an existing file
instead of overwriting it.
</aside>
</section>
<section>
<h3>file to stdin</h3>
<pre><code class="bash"># sort lines and print to stdout
$ sort < myfile.txt
# same, but let's print to a file.
$ sort < myfile.txt > sorted_myfile.txt
</code></pre>
<aside class="notes">
Here we are redirecting a file to stdin.
The second example directs the stdout
of that filter to a file.
</aside>
</section>
<section>
<img src="img/stdstreams-2.svg" alt="std streams" />
<aside class="notes">
You can also redirect from one program to another.
This is where the real power of the Unix philosophy
of composability kicks in. You can feed output from one
program to another.
</aside>
</section>
<section>
<h1>|</h1>
<aside class="notes">
Filtering is indicated
by the almighty pipe. All hail the pipe.
</aside>
</section>
<section>
<pre><code class="bash" data-trim>
# Grab first line, replace tabs with line
# return, and paginate with numbers.
head -1 FLAT_RCL.txt | tr "\t" "\n" | less -N
</code></pre>
</section>
<section>
<h1>Shell it Live!</h1>
<aside class="notes">
We're going to show how each of these commands work.
</aside>
</section>
<section>
<h3>Pipes: How do they work?</h3>
</section>
<section>
<ul>
<li>Each command spawns its own process.</li>
<li>First program starts to push to stdout until it
hits a buffer limit (imposed by your shell of choice).</li>
<li>As soon as it hits the limit, the process is blocked. </li>
<li>First filter process starts reading stdin,
and incrementally starts passing stdout to the next
process.</li>
<li>Some filters must wait until the entire output is available (e.g., sort) before
they can continue, which can buffer to disk.</li>
<li>Continues until the last process is reached.</li>
</ul>
</section>
<section>
<h3>Example from <a href="http://blog.petersobot.com/pipes-and-filters">Peter Sobot</a></h3>
<pre><code class="bash" data-trim>
cat /usr/share/dict/words | # Read in the system's dictionary.
grep purple | # Find words containing 'purple'
awk '{print length($1), $1}' | # Count the letters in each word
sort -n | # Sort lines ("${length} ${word}")
tail -n 1 | # Take the last line of the input
cut -d " " -f 2 | # Take the second part of each line
cowsay -f tux # Print resulting word
</code></pre>
<p>Print out longest word containing 'purple'</p>
</section>
<section>
<img src="img/pipeline_diagram.png" alt="diagram" />
</section>
<section>
<pre><code>
_____________
< unimpurpled >
-------------
\
\
.--.
|o_o |
|:_/ |
// \ \
(| | )
/'\_ _/`\
\___)=(___/
</code></pre>
</section>
<section>
<p><q>"Thanks to the fact that the pipeline only stores what it can process in memory, this solution is very memory-efficient and lightweight. Processing a file of any size would not have changed the memory usage of this solution - the pipeline runs in effectively constant space."</q></p>
</section>
<section>
<h3>This is pretty fast.</h3>
<aside class="notes">
As I will demonstrate in a moment, this is pretty fast.
</aside>
</section>
<section>
<h3> NHTSA's Office of Defects Investigation (ODI) - Recalls - Recalls Flat File</h3>
<p><q>"Manufacturers who determine that a product or piece of original equipment either has a safety defect or is not in compliance with Federal safety standards are required to notify the National Highway Traffic Safety Administration (NHTSA) within 5 business days. "</q></p>
<p>Source: <a href="http://catalog.data.gov/dataset/nhtsas-office-of-defects-investigation-odi-recalls-recalls-flat-file">Data.gov</a></p>
</section>
<section>
<h1>Shell it Live!</h1>
</section>
<section>
<p>If you are repeating yourself...</p>
</section>
<section>
<h3>alias</h3>
<pre><code data-trim>
alias l='ls -lt'
</code></pre>
</section>
<section>
<pre><code data-trim>
$ l
-rw-r--r-- 1 brian staff 108847839 Mar 17 19:35 FLAT_RCL.csv
-rw-r--r-- 1 brian staff 2407 Mar 17 19:16 RCL.txt
-rwxr-xr-x@ 1 brian staff 108847839 Mar 17 04:46 FLAT_RCL.txt
</code></pre>
</section>
<section>
<p>Arguments get tacked on.</p>
<pre><code data-trim>
$ l FLAT_RCL.csv
-rw-r--r-- 1 brian staff 108847839 Mar 17 19:35 FLAT_RCL.csv
</code></pre>
</section>
<section>
<p>But there are limits...</p>
<pre><code data-trim class="bash">
# this would be handy!
$ alias headers = 'head -1 | tr "\t" "\n" | less -N'
# but there's no convenient way to put the filename into the first filter.
$ unalias headers
$ function headers() { head -1 $1 | tr "\t" "\n" | less -N }
# now we're cookin' with fire!
headers FLAT_RCL.txt
</code></pre>
</section>
<section>
<p>Another example...</p>
<pre><code data-trim class="bash">
$ function httphead () {
wget -O - -o /dev/null --save-headers $1 | \
awk 'BEGIN{skip=0}{ if (($0)=="\r") {skip=1;}; \
if (skip==0) print $0 }'
}
$ httphead www.github.com
HTTP/1.1 200 OK
Server: GitHub.com
Date: Tue, 18 Mar 2014 00:56:13 GMT
Content-Type: text/html; charset=utf-8
Status: 200 OK
Cache-Control: private, max-age=0, must-revalidate
Strict-Transport-Security: max-age=31536000
...snip...
</code></pre>
</section>
<section>
<p>Let's say we wanted to see what HTTP headers
Google and Github have in common.</p>
</section>
<section>
<h1>SHELL IT LIVE</h1>
</section>
<section>
<pre><code class="bash" data-trim>
colordiff --side-by-side \
<(httphead google.com | cut -d ":" -f 1 | sort) \
<(httphead github.com | cut -d ":" -f 1 | sort) | \
grep -v "[<>|]"
</code></pre>
</section>
<section>
<h3>xargs</h3>
<p>Your poor man's map function.</p>
<pre><code class="bash" data-trim>
# this will pass all files to tail -1 together
find . -name "*.csv" | xargs tail -1
# this will call tail -1 on each file individually
find . -name "*.csv" | xargs -I {} tail -1 {}
</code></pre>
</section>
<section>
<p>You could live in the shell if you wanted to...</p>
</section>
<section><h3>vim</h3></section>
<section><h3>emacs</h3></section>
<section><h3>lynx</h3><p>(For the masochistic.)</section>
<section>
<p>Wrap-up!</p>
<aside class="notes">
I hope that this talk has given you a
tast of what's available out there, and
you are motivated to read more.
</aside>
</section>
<section>
<h3>Additional Resources</h3>
<ul>
<li><a href="http://blog.petersobot.com/pipes-and-filters">Pipes and Filters</a></li>
<li><a href="https://news.ycombinator.com/item?id=4481234">Unix Commands I Abuse Every DAy</a></li>
<li><a href="http://software-carpentry.org/v4/shell/">Software Carpentry - The Shell</a>
<br/><small>(Thanks, Jason Orendorff!)</small>
</li>
<li><a href="http://www.leancrew.com/all-this/2011/12/more-shell-less-egg/">More Shell, Less Egg</a></li>
<li><a href="http://www.cs.dartmouth.edu/~sinclair/doug/">On McIlroy</a></li>
</ul>
</section>
<section>
<h1>THE END</h1>
<h3>BY Brian Dailey / @byeliad</h3>
<h2>Questions?</h2>
<p><a href="http://dailytechnology.net/talk-cli-intro/">dailytechnology.net/talk-cli-intro</a></p>
<p><small>Thanks to Jason Orendorff, Jason Myers, and others for reviewing.</small></p>
</section>
</div>
</div>
<script src="lib/js/head.min.js"></script>
<script src="js/reveal.min.js"></script>
<script>
// Full list of configuration options available here:
// https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
controls: true,
progress: true,
history: true,
center: true,
theme: Reveal.getQueryHash().theme, // available themes are in /css/theme
transition: Reveal.getQueryHash().transition || 'default', // default/cube/page/concave/zoom/linear/fade/none
// Parallax scrolling
// parallaxBackgroundImage: 'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg',
// parallaxBackgroundSize: '2100px 900px',
// Optional libraries used to extend on reveal.js
dependencies: [
{ src: 'lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: 'plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
{ src: 'plugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } },
{ src: 'plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } }
]
});
</script>
</body>
</html>