├── .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 |
19 |
20 | View on GitHub 21 | 22 |

{{ site.title | default: site.github.repository_name }}

23 |

{{ site.description | default: site.github.project_tagline }}

24 | 25 | {% if site.show_downloads %} 26 |
27 | Download this project as a .zip file 28 | Download this project as a tar.gz file 29 |
30 | {% endif %} 31 |
32 |
33 | 34 | 35 |
36 |
37 | {{ content }} 38 |
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 |
19 |
20 | View on GitHub 21 | 22 |

{{ site.title | default: site.github.repository_name }}

23 |

{{ site.description | default: site.github.project_tagline }}

24 | 25 | {% if site.show_downloads %} 26 |
27 | Download this project as a .zip file 28 | Download this project as a tar.gz file 29 |
30 | {% endif %} 31 |
32 |
33 | 34 | 35 |
36 |
37 | {{ content }} 38 |
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 | --------------------------------------------------------------------------------