├── .gitignore
├── Gemfile
├── Gemfile.lock
├── README.md
├── _config.yml
├── _includes
└── toc.md
├── _layouts
├── _layouts
│ └── default.html
└── default.html
├── _sass
├── jekyll-theme-slate.scss
└── rouge-github.scss
├── assets
├── assets
│ ├── css
│ │ └── style.scss
│ └── images
│ │ ├── bg_hr.png
│ │ ├── blacktocat.png
│ │ ├── icon_download.png
│ │ └── sprite_download.png
└── css
│ └── style.scss
├── history.png
├── index.md
├── prompt1.png
├── script
├── bootstrap
├── cibuild
└── release
├── shell_guide.html
└── slides.md
/.gitignore:
--------------------------------------------------------------------------------
1 | _site
2 | .sass-cache
3 | .jekyll-metadata
4 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | gem 'github-pages', group: :jekyll_plugins
3 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | activesupport (4.2.7)
5 | i18n (~> 0.7)
6 | json (~> 1.7, >= 1.7.7)
7 | minitest (~> 5.1)
8 | thread_safe (~> 0.3, >= 0.3.4)
9 | tzinfo (~> 1.1)
10 | addressable (2.5.1)
11 | public_suffix (~> 2.0, >= 2.0.2)
12 | coffee-script (2.4.1)
13 | coffee-script-source
14 | execjs
15 | coffee-script-source (1.12.2)
16 | colorator (1.1.0)
17 | ethon (0.10.1)
18 | ffi (>= 1.3.0)
19 | execjs (2.7.0)
20 | faraday (0.12.0.1)
21 | multipart-post (>= 1.2, < 3)
22 | ffi (1.9.18)
23 | forwardable-extended (2.6.0)
24 | gemoji (3.0.0)
25 | github-pages (133)
26 | activesupport (= 4.2.7)
27 | github-pages-health-check (= 1.3.3)
28 | jekyll (= 3.4.3)
29 | jekyll-avatar (= 0.4.2)
30 | jekyll-coffeescript (= 1.0.1)
31 | jekyll-default-layout (= 0.1.4)
32 | jekyll-feed (= 0.9.2)
33 | jekyll-gist (= 1.4.0)
34 | jekyll-github-metadata (= 2.3.1)
35 | jekyll-mentions (= 1.2.0)
36 | jekyll-optional-front-matter (= 0.1.2)
37 | jekyll-paginate (= 1.1.0)
38 | jekyll-readme-index (= 0.1.0)
39 | jekyll-redirect-from (= 0.12.1)
40 | jekyll-relative-links (= 0.4.0)
41 | jekyll-sass-converter (= 1.5.0)
42 | jekyll-seo-tag (= 2.1.0)
43 | jekyll-sitemap (= 1.0.0)
44 | jekyll-swiss (= 0.4.0)
45 | jekyll-theme-architect (= 0.0.4)
46 | jekyll-theme-cayman (= 0.0.4)
47 | jekyll-theme-dinky (= 0.0.4)
48 | jekyll-theme-hacker (= 0.0.4)
49 | jekyll-theme-leap-day (= 0.0.4)
50 | jekyll-theme-merlot (= 0.0.4)
51 | jekyll-theme-midnight (= 0.0.4)
52 | jekyll-theme-minimal (= 0.0.4)
53 | jekyll-theme-modernist (= 0.0.4)
54 | jekyll-theme-primer (= 0.1.8)
55 | jekyll-theme-slate (= 0.0.4)
56 | jekyll-theme-tactile (= 0.0.4)
57 | jekyll-theme-time-machine (= 0.0.4)
58 | jekyll-titles-from-headings (= 0.1.5)
59 | jemoji (= 0.8.0)
60 | kramdown (= 1.13.2)
61 | liquid (= 3.0.6)
62 | listen (= 3.0.6)
63 | mercenary (~> 0.3)
64 | minima (= 2.0.0)
65 | rouge (= 1.11.1)
66 | terminal-table (~> 1.4)
67 | github-pages-health-check (1.3.3)
68 | addressable (~> 2.3)
69 | net-dns (~> 0.8)
70 | octokit (~> 4.0)
71 | public_suffix (~> 2.0)
72 | typhoeus (~> 0.7)
73 | html-pipeline (2.5.0)
74 | activesupport (>= 2)
75 | nokogiri (>= 1.4)
76 | i18n (0.8.1)
77 | jekyll (3.4.3)
78 | addressable (~> 2.4)
79 | colorator (~> 1.0)
80 | jekyll-sass-converter (~> 1.0)
81 | jekyll-watch (~> 1.1)
82 | kramdown (~> 1.3)
83 | liquid (~> 3.0)
84 | mercenary (~> 0.3.3)
85 | pathutil (~> 0.9)
86 | rouge (~> 1.7)
87 | safe_yaml (~> 1.0)
88 | jekyll-avatar (0.4.2)
89 | jekyll (~> 3.0)
90 | jekyll-coffeescript (1.0.1)
91 | coffee-script (~> 2.2)
92 | jekyll-default-layout (0.1.4)
93 | jekyll (~> 3.0)
94 | jekyll-feed (0.9.2)
95 | jekyll (~> 3.3)
96 | jekyll-gist (1.4.0)
97 | octokit (~> 4.2)
98 | jekyll-github-metadata (2.3.1)
99 | jekyll (~> 3.1)
100 | octokit (~> 4.0, != 4.4.0)
101 | jekyll-mentions (1.2.0)
102 | activesupport (~> 4.0)
103 | html-pipeline (~> 2.3)
104 | jekyll (~> 3.0)
105 | jekyll-optional-front-matter (0.1.2)
106 | jekyll (~> 3.0)
107 | jekyll-paginate (1.1.0)
108 | jekyll-readme-index (0.1.0)
109 | jekyll (~> 3.0)
110 | jekyll-redirect-from (0.12.1)
111 | jekyll (~> 3.3)
112 | jekyll-relative-links (0.4.0)
113 | jekyll (~> 3.3)
114 | jekyll-sass-converter (1.5.0)
115 | sass (~> 3.4)
116 | jekyll-seo-tag (2.1.0)
117 | jekyll (~> 3.3)
118 | jekyll-sitemap (1.0.0)
119 | jekyll (~> 3.3)
120 | jekyll-swiss (0.4.0)
121 | jekyll-theme-architect (0.0.4)
122 | jekyll (~> 3.3)
123 | jekyll-theme-cayman (0.0.4)
124 | jekyll (~> 3.3)
125 | jekyll-theme-dinky (0.0.4)
126 | jekyll (~> 3.3)
127 | jekyll-theme-hacker (0.0.4)
128 | jekyll (~> 3.3)
129 | jekyll-theme-leap-day (0.0.4)
130 | jekyll (~> 3.3)
131 | jekyll-theme-merlot (0.0.4)
132 | jekyll (~> 3.3)
133 | jekyll-theme-midnight (0.0.4)
134 | jekyll (~> 3.3)
135 | jekyll-theme-minimal (0.0.4)
136 | jekyll (~> 3.3)
137 | jekyll-theme-modernist (0.0.4)
138 | jekyll (~> 3.3)
139 | jekyll-theme-primer (0.1.8)
140 | jekyll (~> 3.3)
141 | jekyll-theme-slate (0.0.4)
142 | jekyll (~> 3.3)
143 | jekyll-theme-tactile (0.0.4)
144 | jekyll (~> 3.3)
145 | jekyll-theme-time-machine (0.0.4)
146 | jekyll (~> 3.3)
147 | jekyll-titles-from-headings (0.1.5)
148 | jekyll (~> 3.3)
149 | jekyll-watch (1.5.0)
150 | listen (~> 3.0, < 3.1)
151 | jemoji (0.8.0)
152 | activesupport (~> 4.0)
153 | gemoji (~> 3.0)
154 | html-pipeline (~> 2.2)
155 | jekyll (>= 3.0)
156 | json (1.8.6)
157 | kramdown (1.13.2)
158 | liquid (3.0.6)
159 | listen (3.0.6)
160 | rb-fsevent (>= 0.9.3)
161 | rb-inotify (>= 0.9.7)
162 | mercenary (0.3.6)
163 | mini_portile2 (2.1.0)
164 | minima (2.0.0)
165 | minitest (5.10.1)
166 | multipart-post (2.0.0)
167 | net-dns (0.8.0)
168 | nokogiri (1.7.1)
169 | mini_portile2 (~> 2.1.0)
170 | octokit (4.6.2)
171 | sawyer (~> 0.8.0, >= 0.5.3)
172 | pathutil (0.14.0)
173 | forwardable-extended (~> 2.6)
174 | public_suffix (2.0.5)
175 | rb-fsevent (0.9.8)
176 | rb-inotify (0.9.8)
177 | ffi (>= 0.5.0)
178 | rouge (1.11.1)
179 | safe_yaml (1.0.4)
180 | sass (3.4.23)
181 | sawyer (0.8.1)
182 | addressable (>= 2.3.5, < 2.6)
183 | faraday (~> 0.8, < 1.0)
184 | terminal-table (1.7.3)
185 | unicode-display_width (~> 1.1.1)
186 | thread_safe (0.3.6)
187 | typhoeus (0.8.0)
188 | ethon (>= 0.8.0)
189 | tzinfo (1.2.3)
190 | thread_safe (~> 0.1)
191 | unicode-display_width (1.1.3)
192 |
193 | PLATFORMS
194 | ruby
195 |
196 | DEPENDENCIES
197 | github-pages
198 |
199 | BUNDLED WITH
200 | 1.14.6
201 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | ---
3 | # What Kai Thinks Every Developer Should Know About The Shell
4 | version 1.0.3
5 |
6 | ©2017 Patrick 'Kai' Leahy. Licensed CC0, but attribution would be polite.
7 |
8 | This is a [quick guide](https://tenebrousedge.github.io/shell_guide/) to the unix shell for people totally new to it.
9 |
10 | It is a work in progress (as all things are). If you have ideas for improvement, please feel free to submit a pull request.
11 | For any inaccuracies, please file an issue.
12 |
13 | I think that I've been winning my fights with jekyll, gh-pages, and CSS, but it's been a bit of a rough show and any contributions to the visual style would be appreciated.
14 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-slate
2 | markdown: kramdown
3 | title: What Kai Thinks Every Developer Should Know About The Shell
4 | description: an opinionated guide to basic shell usage
5 |
--------------------------------------------------------------------------------
/_includes/toc.md:
--------------------------------------------------------------------------------
1 | - [Intended Audience](#intended-audience)
2 | * [Assumed Knowledge](#assumed-knowledge)
3 | - [Summary of Content](#summary-of-content)
4 | - [About the Author](#about-the-author)
5 | - [Starting Out With the Shell](#starting-out-with-the-shell)
6 | * [What is a shell?](#what-is-a-shell)
7 | * [Why learn this?](#why-learn-this)
8 | + [Bash vs zsh](#bash-vs-zsh)
9 | + [Bash Bashing](#bash-bashing)
10 | + [Prezto](#prezto)
11 | - [Navigation](#navigation)
12 | - [Syntax](#syntax)
13 | * [Variables](#variables)
14 | + [How And When To Write A Bash Script](#how-and-when-to-write-a-bash-script)
15 | * [Strings](#strings)
16 | - [Redirection](#redirection)
17 | + [Other Pipeline Elements](#other-pipeline-elements)
18 | - [History](#history)
19 | - [Substitution](#substitution)
20 | + [Printing commands](#printing-commands)
21 | - [Unix Utilities](#unix-utilities)
22 | * [less](#less)
23 | * [find](#find)
24 | + [Silencing Errors](#silencing-errors)
25 | * [grep](#grep)
26 | * [tail and head](#tail-and-head)
27 | * [top and kill](#top-and-kill)
28 | * [Editors: vim, emacs, and nano](#editors-vim-emacs-and-nano)
29 | * [ssh](#ssh)
30 | - [Environment Variables](#environment-variables)
31 | * [$PATH](#path)
32 | * [$CDPATH](#cdpath)
33 | * [$USER, $HOME, $PWD, $OLDPWD](#user-home-pwd-oldpwd)
34 | * [$EDITOR](#editor)
35 | - [Configuration](#configuration)
36 | * [Dotfiles and *.rc files](#dotfiles-and-rc-files)
37 | * [git](#git)
38 | * [nano](#nano)
39 | * [vim](#vim)
40 | - [Cheat Sheet](#cheat-sheet)
41 | - [Problems with this Guide](#problems-with-this-guide)
42 | - [Further Reading](#further-reading)
43 |
--------------------------------------------------------------------------------
/_layouts/_layouts/default.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | {{ site.title | default: site.github.repository_name }}
13 |
14 |
15 |
16 |
17 |
18 |
33 |
34 |
35 |
36 |
39 |
40 |
41 |
42 |
50 |
51 | {% if site.google_analytics %}
52 |
60 | {% endif %}
61 |
62 |
63 |
--------------------------------------------------------------------------------
/_layouts/default.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | {{ site.title | default: site.github.repository_name }}
13 |
14 |
15 |
16 |
17 |
18 |
33 |
34 |
35 |
36 |
39 |
40 |
41 |
42 |
50 |
51 | {% if site.google_analytics %}
52 |
60 | {% endif %}
61 |
62 |
63 |
--------------------------------------------------------------------------------
/_sass/jekyll-theme-slate.scss:
--------------------------------------------------------------------------------
1 | @import "rouge-github";
2 |
3 | /*******************************************************************************
4 | MeyerWeb Reset
5 | *******************************************************************************/
6 |
7 | html, body, div, span, applet, object, iframe,
8 | h1, h2, h3, h4, h5, h6, p, blockquote, pre,
9 | a, abbr, acronym, address, big, cite, code,
10 | del, dfn, em, img, ins, kbd, q, s, samp,
11 | small, strike, strong, sub, sup, tt, var,
12 | b, u, i, center,
13 | dl, dt, dd, ol, ul, li,
14 | fieldset, form, label, legend,
15 | table, caption, tbody, tfoot, thead, tr, th, td,
16 | article, aside, canvas, details, embed,
17 | figure, figcaption, footer, header, hgroup,
18 | menu, nav, output, ruby, section, summary,
19 | time, mark, audio, video {
20 | margin: 0;
21 | padding: 0;
22 | border: 0;
23 | font: inherit;
24 | vertical-align: baseline;
25 | }
26 |
27 | /* HTML5 display-role reset for older browsers */
28 | article, aside, details, figcaption, figure,
29 | footer, header, hgroup, menu, nav, section {
30 | display: block;
31 | }
32 |
33 | ol, ul {
34 | list-style: none;
35 | }
36 |
37 | table {
38 | border-collapse: collapse;
39 | border-spacing: 0;
40 | }
41 |
42 | /*******************************************************************************
43 | Theme Styles
44 | *******************************************************************************/
45 |
46 | body {
47 | box-sizing: border-box;
48 | color:#373737;
49 | background: #212121;
50 | font-size: 16px;
51 | font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif;
52 | line-height: 1.5;
53 | -webkit-font-smoothing: antialiased;
54 | }
55 |
56 | h1, h2, h3, h4, h5, h6 {
57 | margin: 10px 0;
58 | font-weight: 700;
59 | color:#222222;
60 | font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif;
61 | letter-spacing: -1px;
62 | }
63 |
64 | h1 {
65 | font-size: 36px;
66 | font-weight: 700;
67 | }
68 |
69 | h2 {
70 | padding-bottom: 10px;
71 | font-size: 32px;
72 | background: url('../images/bg_hr.png') repeat-x bottom;
73 | }
74 |
75 | h3 {
76 | font-size: 24px;
77 | }
78 |
79 | h4 {
80 | font-size: 21px;
81 | }
82 |
83 | h5 {
84 | font-size: 18px;
85 | }
86 |
87 | h6 {
88 | font-size: 16px;
89 | }
90 |
91 | p {
92 | margin: 10px 0 15px 0;
93 | }
94 |
95 | footer p {
96 | color: #f2f2f2;
97 | }
98 |
99 | a {
100 | text-decoration: none;
101 | color: #007edf;
102 | text-shadow: none;
103 |
104 | transition: color 0.5s ease;
105 | transition: text-shadow 0.5s ease;
106 | -webkit-transition: color 0.5s ease;
107 | -webkit-transition: text-shadow 0.5s ease;
108 | -moz-transition: color 0.5s ease;
109 | -moz-transition: text-shadow 0.5s ease;
110 | -o-transition: color 0.5s ease;
111 | -o-transition: text-shadow 0.5s ease;
112 | -ms-transition: color 0.5s ease;
113 | -ms-transition: text-shadow 0.5s ease;
114 | }
115 |
116 | a:hover, a:focus {text-decoration: underline;}
117 |
118 | footer a {
119 | color: #F2F2F2;
120 | text-decoration: underline;
121 | }
122 |
123 | em {
124 | font-style: italic;
125 | }
126 |
127 | strong {
128 | font-weight: bold;
129 | }
130 |
131 | img {
132 | position: relative;
133 | margin: 0 auto;
134 | max-width: 739px;
135 | padding: 5px;
136 | margin: 10px 0 10px 0;
137 | border: 1px solid #ebebeb;
138 |
139 | box-shadow: 0 0 5px #ebebeb;
140 | -webkit-box-shadow: 0 0 5px #ebebeb;
141 | -moz-box-shadow: 0 0 5px #ebebeb;
142 | -o-box-shadow: 0 0 5px #ebebeb;
143 | -ms-box-shadow: 0 0 5px #ebebeb;
144 | }
145 |
146 | p img {
147 | display: inline;
148 | margin: 0;
149 | padding: 0;
150 | vertical-align: middle;
151 | text-align: center;
152 | border: none;
153 | }
154 |
155 | pre, code {
156 | width: 100%;
157 | color: #222;
158 | background-color: #fff;
159 |
160 | font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
161 | font-size: 14px;
162 |
163 | border-radius: 2px;
164 | -moz-border-radius: 2px;
165 | -webkit-border-radius: 2px;
166 | }
167 |
168 | pre {
169 | width: 100%;
170 | padding: 10px;
171 | box-shadow: 0 0 10px rgba(0,0,0,.1);
172 | overflow: auto;
173 | }
174 |
175 | code {
176 | padding: 3px;
177 | margin: 0 3px;
178 | box-shadow: 0 0 10px rgba(0,0,0,.1);
179 | }
180 |
181 | pre code {
182 | display: block;
183 | box-shadow: none;
184 | }
185 |
186 | blockquote {
187 | color: #666;
188 | margin-bottom: 20px;
189 | padding: 0 0 0 20px;
190 | border-left: 3px solid #bbb;
191 | }
192 |
193 |
194 | ul, ol, dl {
195 | margin-bottom: 15px
196 | }
197 |
198 | ul {
199 | list-style-position: inside;
200 | list-style: disc;
201 | padding-left: 20px;
202 | }
203 |
204 | ol {
205 | list-style-position: inside;
206 | list-style: decimal;
207 | padding-left: 20px;
208 | }
209 |
210 | dl dt {
211 | font-weight: bold;
212 | }
213 |
214 | dl dd {
215 | padding-left: 20px;
216 | font-style: italic;
217 | }
218 |
219 | dl p {
220 | padding-left: 20px;
221 | font-style: italic;
222 | }
223 |
224 | hr {
225 | height: 1px;
226 | margin-bottom: 5px;
227 | border: none;
228 | background: url('../images/bg_hr.png') repeat-x center;
229 | }
230 |
231 | table {
232 | border: 1px solid #373737;
233 | margin-bottom: 20px;
234 | text-align: left;
235 | }
236 |
237 | th {
238 | font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
239 | padding: 10px;
240 | background: #373737;
241 | color: #fff;
242 | }
243 |
244 | td {
245 | padding: 10px;
246 | border: 1px solid #373737;
247 | }
248 |
249 | form {
250 | background: #f2f2f2;
251 | padding: 20px;
252 | }
253 |
254 | /*******************************************************************************
255 | Full-Width Styles
256 | *******************************************************************************/
257 |
258 | .outer {
259 | width: 100%;
260 | }
261 |
262 | .inner {
263 | position: relative;
264 | max-width: 640px;
265 | padding: 20px 10px;
266 | margin: 0 auto;
267 | }
268 |
269 | #forkme_banner {
270 | display: block;
271 | position: absolute;
272 | top:0;
273 | right: 10px;
274 | z-index: 10;
275 | padding: 10px 50px 10px 10px;
276 | color: #fff;
277 | background: url('../images/blacktocat.png') #0090ff no-repeat 95% 50%;
278 | font-weight: 700;
279 | box-shadow: 0 0 10px rgba(0,0,0,.5);
280 | border-bottom-left-radius: 2px;
281 | border-bottom-right-radius: 2px;
282 | }
283 |
284 | #header_wrap {
285 | background: #212121;
286 | background: -moz-linear-gradient(top, #373737, #212121);
287 | background: -webkit-linear-gradient(top, #373737, #212121);
288 | background: -ms-linear-gradient(top, #373737, #212121);
289 | background: -o-linear-gradient(top, #373737, #212121);
290 | background: linear-gradient(top, #373737, #212121);
291 | }
292 |
293 | #header_wrap .inner {
294 | padding: 50px 10px 30px 10px;
295 | }
296 |
297 | #project_title {
298 | margin: 0;
299 | color: #fff;
300 | font-size: 42px;
301 | font-weight: 700;
302 | text-shadow: #111 0px 0px 10px;
303 | }
304 |
305 | #project_tagline {
306 | color: #fff;
307 | font-size: 24px;
308 | font-weight: 300;
309 | background: none;
310 | text-shadow: #111 0px 0px 10px;
311 | }
312 |
313 | #downloads {
314 | position: absolute;
315 | width: 210px;
316 | z-index: 10;
317 | bottom: -40px;
318 | right: 0;
319 | height: 70px;
320 | background: url('../images/icon_download.png') no-repeat 0% 90%;
321 | }
322 |
323 | .zip_download_link {
324 | display: block;
325 | float: right;
326 | width: 90px;
327 | height:70px;
328 | text-indent: -5000px;
329 | overflow: hidden;
330 | background: url(../images/sprite_download.png) no-repeat bottom left;
331 | }
332 |
333 | .tar_download_link {
334 | display: block;
335 | float: right;
336 | width: 90px;
337 | height:70px;
338 | text-indent: -5000px;
339 | overflow: hidden;
340 | background: url(../images/sprite_download.png) no-repeat bottom right;
341 | margin-left: 10px;
342 | }
343 |
344 | .zip_download_link:hover {
345 | background: url(../images/sprite_download.png) no-repeat top left;
346 | }
347 |
348 | .tar_download_link:hover {
349 | background: url(../images/sprite_download.png) no-repeat top right;
350 | }
351 |
352 | #main_content_wrap {
353 | background: #f2f2f2;
354 | border-top: 1px solid #111;
355 | border-bottom: 1px solid #111;
356 | }
357 |
358 | #main_content {
359 | padding-top: 40px;
360 | }
361 |
362 | #footer_wrap {
363 | background: #212121;
364 | }
365 |
366 |
367 |
368 | /*******************************************************************************
369 | Small Device Styles
370 | *******************************************************************************/
371 |
372 | @media screen and (max-width: 992px) {
373 | img {
374 | max-width: 100%;
375 | }
376 | }
377 |
378 | @media screen and (max-width: 480px) {
379 | body {
380 | font-size:14px;
381 | }
382 |
383 | #downloads {
384 | display: none;
385 | }
386 |
387 | .inner {
388 | min-width: 320px;
389 | max-width: 480px;
390 | }
391 |
392 | #project_title {
393 | font-size: 32px;
394 | }
395 |
396 | h1 {
397 | font-size: 28px;
398 | }
399 |
400 | h2 {
401 | font-size: 24px;
402 | }
403 |
404 | h3 {
405 | font-size: 21px;
406 | }
407 |
408 | h4 {
409 | font-size: 18px;
410 | }
411 |
412 | h5 {
413 | font-size: 14px;
414 | }
415 |
416 | h6 {
417 | font-size: 12px;
418 | }
419 |
420 | code, pre {
421 | min-width: 320px;
422 | max-width: 480px;
423 | font-size: 11px;
424 | }
425 |
426 | }
427 |
--------------------------------------------------------------------------------
/_sass/rouge-github.scss:
--------------------------------------------------------------------------------
1 | .highlight table td { padding: 5px; }
2 | .highlight table pre { margin: 0; }
3 | .highlight .cm {
4 | color: #999988;
5 | font-style: italic;
6 | }
7 | .highlight .cp {
8 | color: #999999;
9 | font-weight: bold;
10 | }
11 | .highlight .c1 {
12 | color: #999988;
13 | font-style: italic;
14 | }
15 | .highlight .cs {
16 | color: #999999;
17 | font-weight: bold;
18 | font-style: italic;
19 | }
20 | .highlight .c, .highlight .cd {
21 | color: #999988;
22 | font-style: italic;
23 | }
24 | .highlight .err {
25 | color: #a61717;
26 | background-color: #e3d2d2;
27 | }
28 | .highlight .gd {
29 | color: #000000;
30 | background-color: #ffdddd;
31 | }
32 | .highlight .ge {
33 | color: #000000;
34 | font-style: italic;
35 | }
36 | .highlight .gr {
37 | color: #aa0000;
38 | }
39 | .highlight .gh {
40 | color: #999999;
41 | }
42 | .highlight .gi {
43 | color: #000000;
44 | background-color: #ddffdd;
45 | }
46 | .highlight .go {
47 | color: #888888;
48 | }
49 | .highlight .gp {
50 | color: #555555;
51 | }
52 | .highlight .gs {
53 | font-weight: bold;
54 | }
55 | .highlight .gu {
56 | color: #aaaaaa;
57 | }
58 | .highlight .gt {
59 | color: #aa0000;
60 | }
61 | .highlight .kc {
62 | color: #000000;
63 | font-weight: bold;
64 | }
65 | .highlight .kd {
66 | color: #000000;
67 | font-weight: bold;
68 | }
69 | .highlight .kn {
70 | color: #000000;
71 | font-weight: bold;
72 | }
73 | .highlight .kp {
74 | color: #000000;
75 | font-weight: bold;
76 | }
77 | .highlight .kr {
78 | color: #000000;
79 | font-weight: bold;
80 | }
81 | .highlight .kt {
82 | color: #445588;
83 | font-weight: bold;
84 | }
85 | .highlight .k, .highlight .kv {
86 | color: #000000;
87 | font-weight: bold;
88 | }
89 | .highlight .mf {
90 | color: #009999;
91 | }
92 | .highlight .mh {
93 | color: #009999;
94 | }
95 | .highlight .il {
96 | color: #009999;
97 | }
98 | .highlight .mi {
99 | color: #009999;
100 | }
101 | .highlight .mo {
102 | color: #009999;
103 | }
104 | .highlight .m, .highlight .mb, .highlight .mx {
105 | color: #009999;
106 | }
107 | .highlight .sb {
108 | color: #d14;
109 | }
110 | .highlight .sc {
111 | color: #d14;
112 | }
113 | .highlight .sd {
114 | color: #d14;
115 | }
116 | .highlight .s2 {
117 | color: #d14;
118 | }
119 | .highlight .se {
120 | color: #d14;
121 | }
122 | .highlight .sh {
123 | color: #d14;
124 | }
125 | .highlight .si {
126 | color: #d14;
127 | }
128 | .highlight .sx {
129 | color: #d14;
130 | }
131 | .highlight .sr {
132 | color: #009926;
133 | }
134 | .highlight .s1 {
135 | color: #d14;
136 | }
137 | .highlight .ss {
138 | color: #990073;
139 | }
140 | .highlight .s {
141 | color: #d14;
142 | }
143 | .highlight .na {
144 | color: #008080;
145 | }
146 | .highlight .bp {
147 | color: #999999;
148 | }
149 | .highlight .nb {
150 | color: #0086B3;
151 | }
152 | .highlight .nc {
153 | color: #445588;
154 | font-weight: bold;
155 | }
156 | .highlight .no {
157 | color: #008080;
158 | }
159 | .highlight .nd {
160 | color: #3c5d5d;
161 | font-weight: bold;
162 | }
163 | .highlight .ni {
164 | color: #800080;
165 | }
166 | .highlight .ne {
167 | color: #990000;
168 | font-weight: bold;
169 | }
170 | .highlight .nf {
171 | color: #990000;
172 | font-weight: bold;
173 | }
174 | .highlight .nl {
175 | color: #990000;
176 | font-weight: bold;
177 | }
178 | .highlight .nn {
179 | color: #555555;
180 | }
181 | .highlight .nt {
182 | color: #000080;
183 | }
184 | .highlight .vc {
185 | color: #008080;
186 | }
187 | .highlight .vg {
188 | color: #008080;
189 | }
190 | .highlight .vi {
191 | color: #008080;
192 | }
193 | .highlight .nv {
194 | color: #008080;
195 | }
196 | .highlight .ow {
197 | color: #000000;
198 | font-weight: bold;
199 | }
200 | .highlight .o {
201 | color: #000000;
202 | font-weight: bold;
203 | }
204 | .highlight .w {
205 | color: #bbbbbb;
206 | }
207 | .highlight {
208 | background-color: #f8f8f8;
209 | }
210 |
--------------------------------------------------------------------------------
/assets/assets/css/style.scss:
--------------------------------------------------------------------------------
1 | ---
2 | ---
3 |
4 | @import "jekyll-theme-slate";
5 |
--------------------------------------------------------------------------------
/assets/assets/images/bg_hr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tenebrousedge/shell_guide/65e9e40dff110fd3fe20872a2eab85aef86c552c/assets/assets/images/bg_hr.png
--------------------------------------------------------------------------------
/assets/assets/images/blacktocat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tenebrousedge/shell_guide/65e9e40dff110fd3fe20872a2eab85aef86c552c/assets/assets/images/blacktocat.png
--------------------------------------------------------------------------------
/assets/assets/images/icon_download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tenebrousedge/shell_guide/65e9e40dff110fd3fe20872a2eab85aef86c552c/assets/assets/images/icon_download.png
--------------------------------------------------------------------------------
/assets/assets/images/sprite_download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tenebrousedge/shell_guide/65e9e40dff110fd3fe20872a2eab85aef86c552c/assets/assets/images/sprite_download.png
--------------------------------------------------------------------------------
/assets/css/style.scss:
--------------------------------------------------------------------------------
1 | ---
2 | ---
3 |
4 | @import "{{ site.theme }}";
5 | #markdown-toc {list-style:none;margin:0;padding:0;}
6 | #markdown-toc > li > ul{display:none;}
7 | #markdown-toc > li:hover ul {display:block;list-style:none;}
8 | #markdown-toc li a{text-decoration:none;display:block;margin:.2em 1em;}
9 | #markdown-toc {
10 | position: fixed;
11 | left:2em;
12 | top:4em;
13 | min-height:20em;
14 | background-color: white;
15 | border-radius: 1em;
16 | margin: 1em 0;
17 | width: 20%;
18 | }
19 |
20 | #markdown-toc:hover > li > a:after { margin-left: 5px; content: '\25BC'; }
21 | #markdown-toc li > a:only-child:after { margin-left: 0; content: ''; }
22 |
23 | @media screen and (max-width: 1280px) {
24 | ul#markdown-toc {
25 | position:relative;
26 | left: 0;
27 | top: 0;
28 | width: 100%
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/history.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tenebrousedge/shell_guide/65e9e40dff110fd3fe20872a2eab85aef86c552c/history.png
--------------------------------------------------------------------------------
/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc_levels: 1,2
3 | ---
4 |
5 | version 1.0.3
6 | ©2017 Patrick 'Kai' Leahy. Licensed [CC0][cc0], but attribution would be polite.
7 |
8 | * Table of Contents
9 | {:toc}
10 |
11 | ## Intended Audience
12 |
13 | This guide is specifically written for my classmates at Epicodus.
14 |
15 | ### Assumed Knowledge
16 |
17 | [This page, essentially][epicodus-shell]. You should know what cd, ls, touch, mkdir, mv and rm do. Also, this guide uses
18 |
19 | ```shell
20 | $
21 | ```
22 | to represent the shell prompt. This is a typical convention. Your shell prompt will generally look more like:
23 |
24 | ```shell
25 | Epicodus-9X:~ Guest$
26 | ```
27 |
28 | ## Summary of Content
29 |
30 | This guide will cover basic shell concepts and some recommendations for configuration.
31 |
32 | It will not cover scripting concerns or programming concepts such as loops and other control structures, and it will not cover variable/string manipulation. Those are extremely powerful features but if there's any truth to the [classic quip by jwz][jwz] about the challenges of regular expressions, that goes double for Bash.
33 | This guide will also omit a full description of regular expressions.
34 |
35 | ## About the Author
36 |
37 | Hi, I'm Kai. I grew up in rural Alaska, and I grew up with the Internet. After getting dial-up in 1994 at age 8, the Internet was basically my only link to the outside world. Alaska was awful for me in all sorts of ways. After several attempts I managed to escape its icy clutches, and I found myself half a hemisphere away in Central America. I really wanted to stay down there and so I talked my way into a programming job and taught myself what I needed to know as I went. That worked out more or less okay but in the six years since then I've been mostly stuck working on horrible legacy PHP projects, and Central America didn't turn out to be a good way to meet business contacts. So now I'm putting down some roots in Portland, and loving it so far :)
38 |
39 | I've used Linux exclusively for about ten years now, and have picked up a thing or two, especially since starting work as a programmer. I am currently attending Epicodus to develop my Javascript and Ruby skills.
40 |
41 | ## Starting Out With the Shell
42 |
43 | ![Bash command prompt][prompt1]
44 |
45 | Welcome to the command line. The shell, like git, is a tool that developers love to hate. They both have complicated syntax and a tendency to punish errant keystrokes.
46 | However, they're useful enough that we put up with the rough edges, and the larger the codebase you're working with, the more important they become. It becomes clear pretty quickly that things like `mkdir` and `touch` are much faster than trying to create file and directory structures, but the rest of the shell doesn't exactly go out of its way to teach you what you can do with it, and the [Advanced Bash Scripting Guide][absg] is not exactly light reading.
47 | This guide is also not light reading but should provide a practical introduction to most concepts and some example usage, specifically for someone who wants to be a developer and not a script writer.
48 |
49 |
50 | Learning the shell has been a ten-year process for me, and I'm not really an expert. This guide is the stuff I've learned and found useful. It's definitely not all there is to know about this.
51 |
52 | ### What is a shell?
53 |
54 | The shell is the thing that executes commands and spits text back at you. You generally use this through a terminal program like OSX's Terminal.app. On Windows you might use cygwin or the new Ubuntu substystem.
55 |
56 | In more general terms, the shell is an command interpreter, which means that it's actually a complete programming language of its own. You'll also see the acronym "CLI" thrown around, that stands for "command line interface" as opposed to a "GUI" or "graphical user interface". Either way it's a way to talk to the computer in a fairly direct manner.
57 |
58 | **That is a warning, by the way.**
59 | The problem with programming is that the computer always does exactly what you tell it to. There is a mistake you can make which is worth explaining before we even get past the introduction.
60 |
61 | So you want to remove all the files and folders in some directory, and what you intended to type was this:
62 | ```shell
63 | $ rm -rf /some/path/to/a/file
64 | ```
65 | But you make a small typo:
66 | ```shell
67 | $ rm -rf / some/path/to/a/file
68 | ```
69 | This will remove every file that you have access to. If you have administrator rights you can wipe the whole machine, and OSX at least will not stop you from doing this. **Be careful what you type**. [Test commands to see what they do](#printing-commands) (for example, with `:p`) before trying them for real. [Read the documentation](#unix utilities).
70 | Most of the time the only risk you'll run is having to restore something from source control or backups, but of course that requires you to use those things. And of course the flip side of this is that if you ever do want to do something crazy like type eight characters and wipe the whole machine, you totally can.
71 |
72 | Just remember, with great power comes great responsibility. And yes, that's a line worth stealing ☺
73 |
74 | ### Why learn this?
75 |
76 | Programming is fundamentally a way to save human labor, and that includes our own labor. Learning to use the shell effectively will save you labor as a programmer, and the returns on that investment are exponential. The more time you can spend **thinking** instead of **typing**, the more you can express in code, and the more you can express in code, the more you can change the world.
77 |
78 | ### Bash Bashing
79 |
80 | Bash as a programming language is primitive and ugly as sin, but it will probably run on any Unix-based system without modification. If you really need to be sure of the broadest possible compatibility, there's an even more primitive version of Bash called POSIX, of which you need to know only that it exists. If you have to worry about whether your scripts are compliant with Bash, POSIX, or something else, you should probably try and use some other tool.
81 |
82 | ### Bash vs zsh
83 |
84 | By default on most systems the shell interpreter is a program called Bash. This is basically due to inertia at this point: if you're a shell script writer and don't know in what sort of environment your code will run in, it's best to target Bash since it's the default on basically all systems.
85 | You as a developer should probably use something that sucks somewhat less. My recommendation is to use zsh in combination with the excellent framework [Prezto][prezto]. This guide will note differences between the two where appropriate, but my advice is to just learn zsh.
86 |
87 | Neat features of zsh:
88 |
89 | * Hit tab almost anywhere and zsh will try to do completion (and expansion)
90 | ```shell
91 | $ git branch
92 | ```
93 | Will list both local and remote git branches associated with that repo, as well as recent commits.
94 | * Command correction for known commands (you typed `rgep`, did you mean `grep`?)
95 | * Smart completion for file paths
96 | ```shell
97 | $ mkdir some/long/nested/directory/you/dont/want/to/type
98 | $ cd s/l/n/d/y/d/w/t/t
99 | ```
100 | And hit either tab or enter. Zsh will also tab-complete filenames on remote servers, if that's your cuppa. [Here][zsh-is-better] are some other cool zsh features.
101 |
102 | > Note to Epicodus Students:
103 | To start using `zsh`, you can type `zsh` into any terminal.
104 |
105 | > Note to Mac users:
106 | I hear [iTerm][iterm] is pretty cool.
107 |
108 | ### Prezto
109 |
110 | Prezto is pretty, fast, easily configurable, and user friendly. It does neat things like tab-autocompletion for git branches (and almost everything else you can think of), syntax highlighting as you type, and powerful history tools. I can't really praise it enough, and it's really hard to show you why in plain text, so just use it already ☺
111 |
112 | ## Navigation
113 |
114 | You probably know that you can press the arrow keys up and down to go through commands you've entered before, but there are some other keyboard commands that do useful things.
115 | The way these are typically written is with a caret (^) substituting for the Control key. There's a reason for this notation, but it's kinda [arcane][caretascii].
116 |
117 | The first one you should know is `^C` (ctrl+C). This stops whatever command is currently executing, unless you've locked the system up. If that happens you can probably still use the `kill` command, but you may also contemplate the failures in life that have brought you that point, your worth as a human being, and the fate of your homework assignment before hitting that panic button.
118 |
119 | Usually holding CTRL/CMD and pressing right or left will scroll by word instead of by character. Here are a few more commands:
120 |
121 | * `^D` : this technically means 'end of file' but you use it to get out of things. If you're using zsh but bash is your default shell, pressing this will get you out of zsh and back to bash. This is also what you use to close SSH connections.
122 | * `^A` : jumps to the beginning of the line. You use this when you forget something at the beginning of a command
123 | * `^E` : jumps to the end of the line.
124 | * `^P` and `^N` move backwards and forwards (respectively) in [history][#history].
125 | * `^L` : clears the screen, just like entering `clear` into the terminal.
126 | * `^R` : searches your [history][#history] backwards. This is amazing. My typical use case is when I try a command and it doesn't work, then I spend some time debugging why, then whenever I get done I don't want to hit up a bunch of times looking for that previous command. Hit ^G or escape to stop searching.
127 |
128 | You can also search forwards in history, but the default command for this (`^S`) is usually bound to something else. So in order to do that, you need to have the following in your `.bashrc` or `.zshrc` configuration file:
129 | ```shell
130 | stty -ixon
131 | ```
132 |
133 | For a fuller discussion of the configuration files, see [Configuration](#configuration).
134 |
135 | ## Syntax
136 |
137 | Bash the programming language actually doesn't have a lot of syntax. Pretty much things are commands, strings, or variables.
138 |
139 | ### How And When To Write A Bash Script
140 |
141 | You should dump any series of commands that you plan on typing more than once into a file. Put
142 | ```shell
143 | #!/bin/bash
144 | ```
145 | At the top of the file, and then use `chmod +x` to make it executable.
146 | ```shell
147 | $ chmod +x ~/.local/bin/new_project.sh
148 | ```
149 | Then you can run it by simply typing the name of the file.
150 | ```shell
151 | $ ~/.local/bin/new_project.sh
152 | ```
153 | If the folder your script is in is in your [$PATH](#$PATH) you can just type `new_project.sh` and it will run like any other program.
154 |
155 | Do this for things you were going to end up typing anyway. Epicodus students: script your project creation, or use [this one][new-project-script]. Typing the same thing over and over again is not what programmers do.
156 | If you're doing anything more clever than that, reach for Ruby or Python or even Javascript. For mac users, Homebrew is an pretty good example of shell scripting in Ruby; check out how it works sometime.
157 |
158 | ### Variables
159 | Variables are declared like so:
160 | ```shell
161 | $ FOO="some string"
162 | ```
163 | and used like this:
164 | ```shell
165 | $ echo $FOO
166 | some string
167 | ```
168 | or
169 | ```shell
170 | $ echo ${FOO}
171 | some string
172 | ```
173 |
174 | Variables can be optionally given a [type][bash-types]. Bash supports integers, arrays, and functions.
175 |
176 | And you might think, "variables, great! I'm a programmer, I use those all the time!" Well, not in shell scripts you don't, because you're not developing code that way (hopefully).
177 | Variables are mentioned here for completeness and so you know what they look like. Try to avoid needing to use them. Do set some [environment variables](#environment-variables) though.
178 |
179 | The advanced Bash developer sneers when they read this. They know that Bash variables are powerful and sometimes, the best way to approach a problem with structured text. But if that doesn't happen to describe you, your cue to rewrite your script in another language is probably about thirty lines, or the use of more than one variable.
180 |
181 | ### Strings
182 |
183 | There are several ways to write strings on the command line. Using single quotes:
184 | ```shell
185 | $ 'This is a string!'
186 | ```
187 | Double quotes
188 | ```shell
189 | $ "This is also a string"
190 |
191 | ```
192 | Heredoc
193 | ```shell
194 | $ < search_results.txt
258 | ```
259 | The syntax is:
260 | ```shell
261 | $ some_command > some_filename
262 | ```
263 | The example command finds all files in or underneath the current directory, and the `>` operator writes those to a file. With Bash, `>` will overwrite any existing content without asking questions. Zsh by default will let you know that the file exists already. You can force zsh to overwrite the file anyway with `>|` or `>!`.
264 | If you get a good handle on pipelining, you won't use this terribly often, but if you're doing more complicated things than you can express with a single command it can be useful to store the intermediate output somewhere.
265 |
266 | In the same sort of vein we have `>>` which appends information to a file. For example,
267 | ```shell
268 | $ >>~/.gitconfig <<'EOM'
269 | [color]
270 | ui = true
271 | [core]
272 | autocrlf = input
273 | EOM
274 | ```
275 | I'm liable to use this to add config information to the default `.atom` settings file but that may be the first time I've actually had cause to use this. If you are trying to log something using a shell script you might also find a need for this, but if you're going to log something you may as well use a nicer language to do that with.
276 |
277 | The final bit of redirection that you can do is to take a file and slurp up the contents into command-line arguments with `<`, basically just reversing the operation of `>`.
278 | ```shell
279 | $ grep 'class="red' < search_results.txt
280 | ```
281 |
282 | You will probably use the pipe character daily, and everything else is more situational. The really-final bit of redirection I have never really found a use for, but if you ever need to pretend for a hot minute that the output of a command is a file, you can do:
283 |
284 | ```shell
285 | $ diff <(ls $first_directory) <(ls $second_directory)
286 | ```
287 | The example given would let you compare the contents of two different directories.
288 |
289 | ### Other Pipeline Elements
290 |
291 | So you want to run a bunch of commands on the same line, but you don't want to actually chain their output. You do that like this:
292 | ```shell
293 | $ mkdir -p project/{img,css,js} && touch project/css/styles.css
294 | ```
295 | The `&&` means, 'execute the next command __if the previous one was successful__'. If you do not care whether the commands succeed you can use `;` to separate statements on a single line.
296 | ```shell
297 | $ rmdir project/font; rm index.html
298 | rmdir: failed to remove 'project/font': No such file or directory
299 | rm: remove regular empty file 'index.html'? y
300 | ```
301 | As you can see, the `rm index.html` executed even though the previous command had an error. The last thing that you should know about here is the `&` character. So say you want to start a command, but you don't care about the output at all. Your command is:
302 | ```shell
303 | $ some_command &
304 | ```
305 | > Note:
306 | If you're reading this and you have a good usage example, please submit a pull request.
307 | What this technically does is spawn the new command in what's called a subshell. It will probably be a very long time before you use this, unless you use Linux and have a bad habit of spawning graphical programs from the command line.
308 |
309 | ### Silencing Errors
310 |
311 | This deserves its own little subheader. The idea is that otherwise those errors are going to be passed as input to some other function that's probably expecting only a list of file names. `/dev/null` is a special file that discards all input to it, and the `2>` refers to the error stream.
312 | There is also a `/dev/zero`, `/dev/random`, and `/dev/urandom`, and these spit out zeros or random numbers until you tell them to stop.
313 | Mostly you need to know that these exist, and that you can do more complicated things with redirecting error and input streams if you really need to.
314 |
315 | ## History
316 |
317 | The shell provides some extremely powerful history commands which can basically prevent you from ever having to type anything twice. That's the good news. The bad news is that you need some basic knowledge of regular expressions for this.
318 |
319 | The shell keeps track of every command it executes, up to some configurable limit, usually 1000 by default. If you type `history` it will spit out all of the commands it knows about, with little numbers by them. Slightly more useful is `history 10` (bash) or `history -10` (zsh).
320 | ![shell history][history]
321 | So there are a couple things you're likely to use all the time, and it's good to know that the rest of this stuff exists. I'm going to go throught the long form first because it will help you remember the shortcuts, and it may be useful.
322 |
323 | Firstly, you can redo any command by using its entry number from the history command as so:
324 | ```shell
325 | $ !2205
326 | history.png prompt1.png shell_guide.md
327 | ```
328 | You can also snag (e.g.) the fifth command back
329 | ```shell
330 | $ !-5
331 | ```
332 | But far more often you just want the last command you entered, or some piece of it. On Linux I forget to use `sudo` a lot. `sudo` is "Super User do", and you use it when you want to install a program or do something else which requires elevated privileges. Usually after I get done facepalming I'll do:
333 | ```shell
334 | $ sudo !!
335 | ```
336 | which repeats the entire previous command, with `sudo` in front of it.
337 | You can also snag pieces of the previous command. You may recall that in regular expressions the caret (^) refers to the beginning of something (the line, usually) and the $ refers to the end. So you can type things like this:
338 | ```shell
339 | $ touch abc def ghi
340 | $ echo !!:^
341 | abc
342 | ```
343 | ```shell
344 | $ touch abc def ghi
345 | $ echo !!:1
346 | def
347 | ```
348 | ```shell
349 | $ touch abc def ghi
350 | $ echo !!:$
351 | ghi
352 | ```
353 | And all of that said, the thing that you will find most useful is the shortcut for `!!:$`, which is `!$`. You will very, very often be doing things like this:
354 | ```shell
355 | $ mkdir ~/projects/ruby/new_project
356 | $ cd ~/projects/ruby/new_project
357 | ```
358 | You can instead do
359 | ```shell
360 | $ mkdir ~/projects/ruby/new_project
361 | $ cd !$
362 | ```
363 |
364 | I use that one many times per day.
365 | There are other complicated things you can do if you want, e.g. the third and fifth arguments, or a range of arguments, but generally if I need something like that I'll just hit up and use the ctrl+arrow_key (which if you'll recall goes backwards by word instead of by character) and just make whatever changes on that line. The command `fc` is also used to fix commands, but not by me.
366 |
367 | ## Substitution
368 |
369 | ### Curly Brace Substitution
370 |
371 | Technically using something like `!$` is command substitution, but there a couple of things which deserve their own heading. The first is curly brace substitution, which is extremely useful.
372 | ```shell
373 | $ mkdir -p projectname/{img,css,js,font} && touch projectname/{css/styles.css,js/scripts.js,index.html}
374 | ```
375 | The first part of that expands to
376 | ```shell
377 | $ mkdir -p projectname/img projectname/js projectname/css projectname/font
378 | ```
379 | Other ways to use this:
380 | ```shell
381 | $ mv config{,.backup}
382 | $ mkdir -p ./project/{img,js,css} && touch ./project/{css/styles.css,js/scripts.js,index.html}
383 | $ ln -s /etc/nginx/sites-{available,enabled}/website.local
384 | ```
385 | The first command renames the file `config` to `config.backup`.
386 | The second command makes a folder structure (the `-p` flag creates parent directories as needed) and creates some files inside it.
387 | The third command is what you would use to enable an nginx website. `ln -s` creates a **symlink**, which is just a pointer to a file.
388 |
389 | ### Caret Substitution
390 | Another really useful thing is caret substitution, which just swaps one string for another in the previous command.
391 | ```shell
392 | $ ls some_file
393 | -rw-rw-r-- 1 kai kai 0 Mar 20 16:50 some_file
394 | $ ^ls^rm
395 | rm: remove regular empty file 'some_file'? y
396 | ```
397 | Here we have swapped `ls` with `rm` -- the idea being to verify that the file exists, and then to remove it.
398 |
399 | ### Global Substitution
400 |
401 | If you need to replace a string that occurs multiple times in the previous command you can do this:
402 | ```shell
403 | $ touch spam spamspam spamspamspam spameggsausageandspam
404 | $ !!:gs/spam/meow/:p
405 | touch meow meowmeow meowmeowmeow meoweggsausageandmeow
406 | ```
407 | `gs` here stands for 'global substitution', and the `:p` bit at the end of the history command prints it instead of executing it.
408 |
409 | ### Printing commands
410 |
411 | The `:p` trick doesn't work for everything. As far as I know it only really works for history expansion.
412 | If you have typed out something and you're not sure what it might expand to, use `echo [the rest of the command]`.
413 |
414 | ### Aliases
415 |
416 | If there is some command that you type often, you can save yourself some time by using an alias.
417 |
418 | ```shell
419 | $ alias gpo='git push origin HEAD'
420 | ```
421 |
422 | In the example above typing `gpo` would execute `git push origin HEAD`. Spaces aren't allowed after the equals sign. This alias will only persist until you close the window. If you want to make that a permanent alias, you have to put that line in your `~/.bashrc` or `~/.zhsrc` file.
423 |
424 | Don't go hog-wild with aliases, or at least if you do, remember the commands that they're replacing, so that you don't get confused when sitting down to a new machine. Prezto and other frameworks include various helpful sets of aliases for git commands, ruby tasks, and many other common tools.
425 |
426 |
427 | ## Unix Utilities
428 |
429 | The unix toolbox, comprising the shell and utilities, is ludicrously powerful, which probably has something to do with why you can get them on every major computing platform including (finally) Windows.
430 | *I do not have a good handle on sed or awk. If someone wants to contribute a short description of the use of those tools, please submit a pull request.*
431 | *Note for anyone else: the reason why I don't have a good handle on these is that they're complex and not usually necessary*
432 |
433 | ### Finding help
434 | Almost all of the command line tools have a manual, unless it's something built in to the shell like `echo`. Type in (e.g.) `man find` and you will be inundated with information.
435 | If you're using something like `bower` which does not ship with a [manpage][manpage], you should be able to get a quick usage guide by passing it the `--help` flag.
436 | If the tool is extremely badly behaved and does not respond to the `--help` flag, you can try `-h`. If none of that works throw away the tool and complain to the author.
437 |
438 | It should probably be mentioned that these tools were all written by different people and the flags and invocation tend to be somewhat idiosyncratic. `dd` is probably the best example of this. It's a tool you use to copy binary data in very specific ways, but its syntax is like no other utility, because it was written for some obscure IBM system, and there's no point in changing the syntax of a tool that is in wide use already.
439 |
440 | It's not entirely the case that the shell is buggy and inconsistent. It's at least more inconsistent than buggy. All together though, it works pretty well.
441 |
442 | ### less
443 |
444 | This tool (called a pager) is for when you have a command that spits out ten zillion lines of text and you care about some part of it, or for when you want to just view a file really quickly. Hit 'h' for the help menu, and 'q' to quit.
445 | ```shell
446 | $ brew search ruby | less
447 | ```
448 | ```
449 | $ less .gitignore
450 | ```
451 | You can use `cat` to view short files, but anything longer than 40 lines is probably best viewed with `less`. It has some search abilities and other useful features.
452 | The one thing it's not great at is viewing files that are being updated continually (logfiles). For that use `tail -f`.
453 | [Prezto][prezto] has a neat feature where if you type `less` it will figure out how long the file is and if it's only one page it just dumps the text to the terminal.
454 |
455 | ### find
456 |
457 | `find` is brilliant. The general form is:
458 | ```shell
459 | $ find [location] [options]
460 | ```
461 |
462 | You use this when you want to get a list of filenames in a subdirectory that match certain criteria, and especially when you want to do that and then do some sort of function to them. Usually I will use the case-insensitive name search and a glob (wildcard) operator (*).
463 |
464 | ```shell
465 | $ find /etc -iname '*.ini'
466 | ```
467 | It's good for things where you know some part of the filename but don't know where it might be. You can also use it to find files that have been modified within a certain timeframe, and you can limit how deep it searches too.
468 | Many uses of `find` can be avoided with zsh, which has a `**` operator which recursively matches subdirectories, so you can do things like
469 |
470 | ```shell
471 | $ rm -i ~/**/*.class
472 | ```
473 | Normally `find` is just used to list some files, but it also has an `-exec` option which is often a convenient way to apply a command to the matching files. `Find` uses `{}` to represent the file. Why? Hell if I know.
474 | ```shell
475 | find . -type f -name "*.php" 2>/dev/null -exec php -l {} \; | grep -v 'No syntax errors'
476 | ```
477 | This does a syntax check on all PHP files and prints the ones that don't pass. Inheriting a repository where the above command is necessary is not fun, by the way. I don't particularly remember why the `2>/dev/null` part was necessary, but for the record that's how you get rid of error streams you don't want.
478 |
479 | ### grep
480 |
481 | `grep` is just a text search function just like the ones in whichever graphical code editor you use, but the difference is that you get to use it with the rest of the unix toolchain. You can ask it to look for either literal text or (at least as often) a regular expression.
482 |
483 | ```shell
484 | $ grep -r 'console.log' ./*
485 | ```
486 | The above command will recursively search for the matching string in __all files in the current directory__ (`./*`) (here the idea is to remove debugging statements before committing). However, if I'm feeling slightly less lazy and want to be more specific about what files are searched:
487 | ```shell
488 | $ grep 'console.log' ./**/*.js
489 | ```
490 | A slightly contrived example to show `grep` chaining:
491 | ```shell
492 | $ brew search ruby | grep rails | grep -v jquery | grep -v redis
493 | ```
494 | That lists ruby packages that contain the string 'rails' but not 'jquery' or 'redis'. Doing that any other way sounds like a lot of work.
495 |
496 | ### tail and head
497 |
498 | `tail` is used mostly for snagging the last few lines of an error log file, but as that is an occupational hazard for programmers (like the shell itself!) then it's actually pretty useful just for that.
499 | ```
500 | $ tail -n 30 /var/log/nginx/error.log
501 | ```
502 | You can also use it to watch files as they are being generated, with `tail -f`. `tail` is also used to grab the last few lines of some command output, generally some sort of sorted data. `head` is the reverse command, grabbing the first few lines of a file or of some command output. It's less useful, but if all you use it for is [listing large files in a directory](#redirection) then it's still worth knowing.
503 |
504 | ### top and kill
505 |
506 | `top` is a process monitor that lists things in order of CPU usage by default. It can kill things too if you press 'k'. It will ask you what you want, and default to the highest-cpu-utilizing process. But if you have used the amazing power of your terminal to really lock up the system, your panic button is:
507 | ```shell
508 | $ kill -9 $(pgrep chrome)
509 | ```
510 | If you happen to know the process id you can give that to kill:
511 | ```shell
512 | $ kill -9 1233
513 | ```
514 | `kill -9` is an extremely rude way to end a process, and the process might be rude back. If your system is locked up and it's something less than a critical emergency, use your smartphone to Google the things you should do before using that particular number.
515 |
516 | ### Editors: vim, emacs, and nano
517 |
518 | If you learn `vim`, you will never need another text editor. If you want to learn `vim`, there is a learning game called ["vim adventures"][vim-adventures] which should get you on the right path.
519 | So far I'm not that clever.
520 | vim is part of the POSIX specification and should be installed by default on any system with a unix-based shell (which since Microsoft created a Ubuntu subsystem is all of them).
521 | `emacs` deserves a mention; it used to be pretty much a 50/50 split between it and `vim`, but it [lost][vimwon] the [Editor Wars][editorwars]. Reasons to use it would be "I want a command line editor, but `vim` is too hard, and I like Lisp and wearing out the control keys on my keyboard".
522 |
523 | My preferred editor is Sublime Text, but on the command line I like `nano`.
524 | Generally the only time I use this is when editing configuration files, but sometimes it's useful for doing quick editing on a staging server. I should probably get around to learning `vim` but it does take a little while to get productive with it. I suspect that the easiest way to learn is to simply use it exclusively for a week.
525 | However, if you want a stupid-simple editor for quick config file editing, `nano` is hard to beat. It very helpfully prints all its commands at the bottom of the screen, and it can be made to do [syntax highlighting](#nano) too.
526 |
527 | ### ssh
528 |
529 | `ssh` gives you secure command-line access to some other system. This is mostly useful for server administration, which you will do eventually in some capacity. It's also used by git to talk to remote repositories like (e.g.) GitHub.
530 | If you're getting tired of typing your GitHub username and password into the CLI every time you want to push some code, congratulations! There's a better way. Unfortunately for my fellow classmates, we don't get to use this.
531 | Which is to say, if you want to generate a new keypair every day, uploading it to GitHub and deleting the old one, knock yourself out.
532 | However, since most people will not do this, this section is going to be something less than a full explanation.
533 |
534 | Most often with `ssh` you will be opening a shell on another system, and you may or may not take the time to get your aliases and such set up there. However, if you already know what you want:
535 | ```shell
536 | $ ssh hostname 'ls -lha ~'
537 | $ ssh hostname 'pg_dump -u user some_database' > database_dump.sql
538 | ```
539 |
540 | You can also use `ssh` to set up proxies and tunnels, but you probably won't. Do practice good [infosec][infosec] with this tool.
541 | +**Your private keys need to be protected.**
542 | +Never create a private key without a passphrase.
543 | +Never re-use a key: create one for each site that you want to access, for each machine you access that site with.
544 | `ssh-agent` will let you get away with only typing the passphrase for your keys once per session.
545 |
546 | ### Further Reading
547 |
548 | There are dozens or hundreds of other shell commands which you might find useful, especially in pipelines. You may want to look into the [Posix toolset][posix], or find out what [Awesome][awesome-shell] stuff you can do with the shell.
549 |
550 | ## Environment Variables
551 |
552 | There are a bunch of what are called "environment variables" that are either always set or that are very useful to set.
553 |
554 | ### $PATH
555 |
556 | This is a critical part of how your shell works. This contains all the places that your shell will look to find executables. It's always set for you, but you may want to add other folders to it.
557 | ```shell
558 | $ echo $PATH
559 | /home/kai/.rbenv/shims:/home/kai/.rbenv/bin:/home/kai/.local/bin:/usr/local/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
560 | ```
561 | The format is paths separated by colons. The usual command to add to it is:
562 | ```shell
563 | PATH=$PATH:/something new
564 | ```
565 | That makes sure that you don't overwrite some important bit of it. If you happen to do that, you will suddenly lose access to lots of commands.
566 | On the other hand, you can drop your scripts into any folder listed in your `$PATH` and set them to executable (`chmod +x`) and they will be available on the command line for you to call like any other program.
567 |
568 | ### $CDPATH
569 |
570 | This is not a critical part of how your shell works, but it's still super useful. If you have all your project folders in a particular place (`~/Desktop`, e.g.) you can set your $CDPATH to that folder and then cd to any subdirectory without worrying about where you are.
571 | ```shell
572 | $ CDPATH=~/Desktop/
573 | $ ls ~/Desktop/
574 | project1 project2 projectmeow
575 | $ cd /etc/nginx/sites-available/
576 | $ cd projectmeow
577 | ~/Desktop/projectmeow
578 | ```
579 |
580 | ### $USER, $HOME, $PWD, $OLDPWD
581 |
582 | These are set by the shell automatically and they can be kinda useful.
583 |
584 | * $USER : This is always equal to the current user's username
585 | * $HOME : This is the user's home directory. If you're writing scripts use this and not ~
586 | * $PWD : This is the current working directory
587 | * $OLDPWD : This is the previous working directory
588 |
589 | Typing `cd -` will take you to the directory specified by `$OLDPWD`. This is useful for when you want to execute a command in some folder but still keep working where you're currently at.
590 |
591 | ```shell
592 | $ cd ~/Documents/shell_guide && git add -u && git commit -m "adding one character to improve an example" && git push origin HEAD && cd -
593 | ```
594 |
595 | ### $EDITOR
596 |
597 | This is used by various command-line tools, including git. If you want to edit your commit messages with atom, you can set
598 | ```shell
599 | $ EDITOR='atom'
600 | ```
601 | or in your `~/.bashrc` or `~/.zshrc` file
602 | ```shell
603 | export EDITOR='atom'
604 | ```
605 | On my system this is set to `nano` because it's pretty rare that this gets invoked on something where you want to have a more fully featured editor. More advanced users will set it to `vim`.
606 |
607 | ## Configuration
608 |
609 | ### Dotfiles and *.rc files
610 |
611 | Many tools will read an rc file on startup. Most shells will read quite a number of files on startup. Not all of them will be relevant to your interests.
612 | There are some files that are read when you are using the shell interactively and some that are run for non-interactive shells (startup scripts, e.g.).
613 |
614 | The files you care about are `~/.bash_profile` and (far more often) `~/.bashrc` if you're using Bash. If you're using zsh then you care about `~/.zshrc`. This is where you will put your custom aliases, and set $EDITOR, add anything you need to your $PATH, set up a colorful prompt, and other such things.
615 |
616 | If you want to reload your configuration, the following lines are equivalent:
617 | ```shell
618 | $ . ~/.zshrc
619 | $ source ~/.zshrc
620 | ```
621 |
622 | You also have dotfiles which are configuration for various things. Those are the hidden files that begin with a period. Changing any of the config options is, well, optional, but you may want to do so.
623 | Generally it's a good idea to [keep your dotfiles under source control][git-dotfile] but it's slightly trickier to get those set up on a new machine than your normal git repo, so if you do this, make a script that does these steps for you.
624 |
625 | ### git
626 |
627 | `git` has a number of configuration options which you should set using `git --config` instead of writing to `~/.gitconfig` directly.
628 | It also has 'hooks', which are scripts it can run before or after you commit things.
629 | +Post-commit hooks might be useful for, e.g. pushing the commits automatically to one or more repositories.
630 | +Pre-commit hooks are vitally important and will save you from many stupid mistakes.
631 | Yelp has a project called [pre-commit][precommit] that gives you lots of useful pre-commit options out of the box.
632 |
633 | You will want to do a syntax check for any css, javascript, ruby or java files that you add to a repository.
634 | You will want to trim trailing whitespace.
635 | You will want to check for debugging statements so that those don't get into production code.
636 | This guide will be updated at some point with more explicit instructions on how to do that.
637 |
638 | A full description of git's config options is somewhat out of scope for this guide. Check [here][git-config] for more info.
639 |
640 | You will potentially want to add things to your `~/.gitignore` file. On OSX having `.DS_Store` in there is not really optional. GitHub has a collection of [useful .gitignore files][github-gitignore]
641 |
642 | ### nano
643 |
644 | On Linux, `nano` comes with a bunch of syntax highlighting files in `/usr/share/nano`. Drop this into your '~/.nanorc' file:
645 | ```shell
646 | include /usr/share/nano/*
647 | ```
648 | Those will do pretty well. For those using other systems, there's also a GitHub repo with [improved nano highlighting][nanocolor] that you may want to use.
649 |
650 | ### vim
651 |
652 | Someone needs to teach me this so I can write this section.
653 |
654 | ## Cheat Sheet
655 |
656 | It is strongly recommended that you create your own. This will firm up memory associations.
657 |
658 | ## Problems with this Guide
659 |
660 | I use zsh on Linux, so I expect there to be some differences with e.g. keyboard commands on OSX. Please file an issue in the repository and I will update this accordingly. Editing suggestions for style and content should also be reported similarly.
661 |
662 | ## Further Reading
663 |
664 | * [The Advanced Bash Scripting Guide][absg]
665 | * [Zsh Documentation](http://zsh.sourceforge.net/Doc/)
666 | * [History of Character Encodings](http://tronweb.super-nova.co.jp/characcodehist.html)
667 | * [Why Ctrl-D exits the shell](http://unix.stackexchange.com/questions/110240/why-does-ctrl-d-eof-exit-the-shell)
668 | * [Unix Hater's Handbook](http://web.mit.edu/~simsong/www/ugh.pdf) (rather dated by now)
669 | * [The Shell Hater's Handbook](http://shellhaters.org/) [video](http://confreaks.tv/videos/gogaruco2010-the-shell-hater-s-handbook)
670 | Recommended:
671 |
672 | * [Slashdot](https://slashdot.org)
673 | * [Hacker News](https://news.ycombinator.com)
674 | * [Why's Poignant Guide to Ruby](http://poignant.guide/)
675 | * [Vim adventures][vim-adventures]
676 |
677 | [epicodus-shell]: https://www.learnhowtoprogram.com/intro-to-programming/getting-started-with-intro-to-programming/interacting-with-the-command-line
678 | [jwz]: http://regex.info/blog/2006-09-15/247
679 | [prezto]: https://github.com/sorin-ionescu/prezto
680 | [prompt1]: prompt1.png
681 | [absg]: http://tldp.org/LDP/abs/html/
682 | [caretascii]: https://en.wikipedia.org/wiki/Caret_notation
683 | [history]: history.png
684 | [editorwars]: http://en.wikipedia.org/wiki/Editor%20wars
685 | [vimwon]: http://www.linux-magazine.com/Online/Blogs/Off-the-Beat-Bruce-Byfield-s-Blog/The-End-of-the-Editor-Wars
686 | [nanocolor]: https://github.com/scopatz/nanorc
687 | [precommit]: https://pre-commit.com
688 | [git-dotfile]: https://developer.atlassian.com/blog/2016/02/best-way-to-store-dotfiles-git-bare-repo/
689 | [git-config]: https://git-scm.com/docs/git-config
690 | [pry-repl]: http://pryrepl.org/
691 | [vim-adventures]: https://vim-adventures.com/
692 | [cc0]: https://wiki.creativecommons.org/wiki/CC0
693 | [mangpage]: https://en.wikipedia.org/wiki/Man_page
694 | [infosec]: https://en.wikipedia.org/wiki/Information_security
695 | [iterm]: https://www.iterm2.com/
696 | [brew]: https://github.com/Homebrew/brew/
697 | [bash-types]: http://www.tldp.org/LDP/abs/html/declareref.html
698 | [new-project-script]: https://github.com/tenebrousedge/new_project_script
699 | [github-gitignore]: https://github.com/github/gitignore
700 | [zsh-is-better]: https://www.slideshare.net/jaguardesignstudio/why-zsh-is-cooler-than-your-shell-16194692
701 | [posix]: http://shellhaters.org/
702 | [bash-one-liners]: http://www.bashoneliners.com/
703 | [awesome-shell]: https://github.com/alebcay/awesome-shell
704 |
--------------------------------------------------------------------------------
/prompt1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tenebrousedge/shell_guide/65e9e40dff110fd3fe20872a2eab85aef86c552c/prompt1.png
--------------------------------------------------------------------------------
/script/bootstrap:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | gem install bundler
6 | bundle install
7 |
--------------------------------------------------------------------------------
/script/cibuild:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | bundle exec jekyll build
6 | gem build jekyll-theme-slate.gemspec
7 |
--------------------------------------------------------------------------------
/script/release:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Tag and push a release.
3 |
4 | set -e
5 |
6 | # Make sure we're in the project root.
7 |
8 | cd $(dirname "$0")/..
9 |
10 | # Make sure the darn thing works
11 |
12 | bundle update
13 |
14 | # Build a new gem archive.
15 |
16 | rm -rf jekyll-theme-slate-*.gem
17 | gem build -q jekyll-theme-slate.gemspec
18 |
19 | # Make sure we're on the master branch.
20 |
21 | (git branch | grep -q 'master') || {
22 | echo "Only release from the master branch."
23 | exit 1
24 | }
25 |
26 | # Figure out what version we're releasing.
27 |
28 | tag=v`ls jekyll-theme-slate-*.gem | sed 's/^jekyll-theme-slate-\(.*\)\.gem$/\1/'`
29 |
30 | # Make sure we haven't released this version before.
31 |
32 | git fetch -t origin
33 |
34 | (git tag -l | grep -q "$tag") && {
35 | echo "Whoops, there's already a '${tag}' tag."
36 | exit 1
37 | }
38 |
39 | # Tag it and bag it.
40 |
41 | gem push jekyll-theme-slate-*.gem && git tag "$tag" &&
42 | git push origin master && git push origin "$tag"
43 |
--------------------------------------------------------------------------------
/shell_guide.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Kai's Guide Moved
5 |
6 |
9 |
10 |
11 |
12 | This page exists because I failed to name the main document index.md and then shared the link a few times.
13 | Lesson learned. The page redirection techniques were borrowed from , which is at the moment still listed on GitHub's examples of fine GH-Pages sites .
14 |
15 |
16 |
--------------------------------------------------------------------------------
/slides.md:
--------------------------------------------------------------------------------
1 | # How to be Awesome at the Shell
2 | by Kai
3 |
4 | ---
5 |
6 | ## About Kai
7 |
8 | * weird
9 | * from the Internet
10 | * mostly harmless
11 | * unreasonably familiar with Linux
12 |
13 | ---
14 |
15 | ## Why learn the shell?
16 |
17 | The point of programming is to save labor, and saving our own labor has exponential returns. The more time you can spend **thinking** instead of **typing**, the more you can achieve as a programmer, and the more you can change the world.
18 |
19 | note:
20 | That holds true for many other tools as well, but the shell is something that you use every day, and as far as I can tell there's no formal instruction in the shell to be had anywhere.
21 |
22 | ---
23 |
24 | ## Bash
25 |
26 | Bash is:
27 |
28 | * a command-line interpreter
29 | * a complete programming language
30 | * a ridiculous holdover from the 1970s that no one should ever use
31 |
32 | note:
33 | Bash is both a bad programming language and a bad interpreter. Use bash to save keystrokes and construct commands. Do not use it for general purpose programming or automating systems processes. bash is great for structured text, preferably many different kinds of structured text
34 |
35 | ---
36 |
37 | ## Zsh and Prezto
38 |
39 | Do not leave $HOME without them!
40 |
41 | * tab complete all the things
42 | -- partial file names
43 | -- git branches
44 | -- rake commands
45 | -- and more!
46 |
47 | * syntax highlighting as you type
48 | * pretty prompts
49 | * useful aliases
50 |
51 | ---
52 |
53 | ## Controls
54 |
55 | ---
56 |
57 | ## Navigation:
58 |
59 | * up, down : scroll through history
60 | * Ctrl-A : jump to beginning of line
61 | * Ctrl-E : jump to end of line
62 | Search:
63 | * Ctrl-R : search backwards through history.
64 | * Ctrl-S : search forwards through history
65 |
66 | ---
67 |
68 | ## Substitution
69 |
70 | ---
71 |
72 | ## Aliases
73 |
74 | These are strings which are expanded when you enter them into the terminal.
75 | Use them to shorten commands:
76 |
77 | ```shell
78 | $ alias gpo='git push origin HEAD'
79 | $ alias gcm='git checkout master'
80 | ```
81 |
82 | ---
83 |
84 | ## Curly Brace Substitution
85 |
86 | This expands both strings and ranges within curly braces.
87 |
88 | ```shell
89 | $ echo {string1,string2}/abc
90 | string1/abc string2/abc
91 | ```
92 | or
93 | ```shell
94 | $ echo {0..3}/{c..f}
95 | 0/c 0/d 0/e 0/f 1/c 1/d 1/e 1/f 2/c 2/d 2/e 2/f 3/c 3/d 3/e 3/f
96 | ```
97 |
98 | ---
99 |
100 | ## Examples
101 |
102 | ```shell
103 | $ mkdir -p project_name/{img,css,js}
104 | ```
105 |
106 | ```shell
107 | $ ln -s /etc/nginx/sites-{available,enabled}/my_site_config
108 | ```
109 |
110 | ---
111 |
112 | ## Caret Substitution
113 |
114 | Use this when you want to edit one word in the previous command.
115 |
116 | ```shell
117 | $ echo "some thing"
118 | some thing
119 | $ ^thing^foo^
120 | some foo
121 | ```
122 |
123 | You can use this to fix typos or if the command you want differs from the previous one by only one word.
124 |
125 | ---
126 |
127 | ## Global Substitution
128 |
129 | When you want to replace all instances of a string in the previous command, you can use global substitution:
130 |
131 | ```shell
132 | $ echo 'spam sausage spam spam bacon spam tomato and spam'
133 | spam sausage spam spam bacon spam tomato and spam
134 | $ !!:gs/spam/meow/
135 | meow sausage meow meow bacon meow tomato and meow
136 | ```
137 |
138 | note:
139 | I have no solid use cases for this, but it's good to know it exists.
140 |
141 | ---
142 |
143 | ## History
144 |
145 | Bash keeps a record of everything you type, just like Google and the NSA.
146 | You can access this history in various ways. The most important ones are:
147 |
148 | * `!!` : the entire previous line
149 | * `!$` : the last word of the previous line
150 | * `!`number : the line of history with the matching number
151 |
152 | note:
153 | also introduce history command, !-n notation, and !!:$ !!:^ !!:0
154 |
155 | ---
156 |
157 | ## Redirection
158 |
159 | ---
160 |
161 | ## Pipes
162 |
163 | One of the more significant inventions in programming history. This guy is the heart and soul of the command line.
164 |
165 | ```shell
166 | $
167 | ```
168 | ---
169 |
170 | ## Redirection - stderr
171 |
172 | ---
173 |
174 | ## Redirection - File IO
175 |
176 | ---
177 |
--------------------------------------------------------------------------------