<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Balthazar Rouberol</title>
    <description>The latest articles on DEV Community by Balthazar Rouberol (@brouberol).</description>
    <link>https://dev.to/brouberol</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F350721%2F34005c90-12e5-4d2e-ad5e-dce4fc02d2c0.jpeg</url>
      <title>DEV Community: Balthazar Rouberol</title>
      <link>https://dev.to/brouberol</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/brouberol"/>
    <language>en</language>
    <item>
      <title>Shell Productivity Tips and Tricks</title>
      <dc:creator>Balthazar Rouberol</dc:creator>
      <pubDate>Fri, 24 Apr 2020 15:23:44 +0000</pubDate>
      <link>https://dev.to/brouberol/shell-productivity-tips-and-tricks-1o1g</link>
      <guid>https://dev.to/brouberol/shell-productivity-tips-and-tricks-1o1g</guid>
      <description>&lt;p&gt;Initially published on my &lt;a href="https://blog.balthazar-rouberol.com/shell-productivity-tips-and-tricks"&gt;blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;
    This article is part of a self-published book project by Balthazar Rouberol and &lt;a href="https://etnbrd.com"&gt;Etienne Brodu&lt;/a&gt;, ex-roommates, friends and colleagues, aiming at empowering the up and coming generation of developers. We currently are hard at work on it!
&lt;/p&gt;

&lt;p&gt;
  If you are interested in the project, we invite you to join the &lt;a href="https://balthazar-rouberol.us4.list-manage.com/subscribe?u=1f6080d496af07a836270ff1d&amp;amp;id=81ebd36adb"&gt;mailing list&lt;/a&gt;!
&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Tab completion&lt;/li&gt;
&lt;li&gt;Keyboard shortcuts&lt;/li&gt;
&lt;li&gt;Navigating through history&lt;/li&gt;
&lt;li&gt;Shell expansions&lt;/li&gt;
&lt;li&gt;Real-life examples&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;li&gt;Going further&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Shell productivity tips
&lt;/h1&gt;

&lt;p&gt;I estimate that I spend around 50% of my day working in my text editor&lt;br&gt;
and my terminal. Any way I can get more productive in these environments&lt;br&gt;
has a direct and measurable impact on my daily productivity as a whole.&lt;/p&gt;

&lt;p&gt;If you spend a good chunk of your day repeatedly hitting the left and&lt;br&gt;
right arrow keys to navigate in long commands or correct typos, or&lt;br&gt;
hitting the up or down arrow keys to navigate your command history, this&lt;br&gt;
chapter should help you get more done quicker. We will cover some shell&lt;br&gt;
features you can leverage to make your shell do more of the work for&lt;br&gt;
you.&lt;/p&gt;

&lt;p&gt;On a personal level, I probably use some of these up to 30 times a day,&lt;br&gt;
sometimes even without thinking about it, and it gives me a real sense&lt;br&gt;
of ownership of my tool.&lt;/p&gt;

&lt;p&gt;In the immortal words of Kimberly “Sweet Brown” Wilkins:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ain't nobody got time for that.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a id="tab-completion"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Tab completion
&lt;/h2&gt;

&lt;p&gt;When you are typing in your shell, I suggest you treat the&lt;br&gt;
Tab key as a superpower. Indeed, the same way your phone&lt;br&gt;
keyboard can autocomplete words for you, so can your shell. It can&lt;br&gt;
suggest completions of command names and even command arguments or&lt;br&gt;
options! This works by pressing Tab (twice for &lt;code&gt;bash&lt;/code&gt; and&lt;br&gt;
once for &lt;code&gt;zsh&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: One of the reasons &lt;code&gt;zsh&lt;/code&gt; might be favored over &lt;code&gt;bash&lt;/code&gt; is its more&lt;br&gt;
powerful auto-completion system, giving more results out-of-the-box and&lt;br&gt;
allowing you to navigate through the auto-completion options.&lt;/p&gt;

&lt;p&gt;Here is an example of &lt;code&gt;bash&lt;/code&gt; auto-completing a command name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mkd&amp;lt;Tab&amp;gt;
mkdep  &lt;span class="nb"&gt;mkdir&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here is an example of &lt;code&gt;bash&lt;/code&gt; auto-completing a command argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;man mkd&amp;lt;Tab&amp;gt;
&lt;span class="nb"&gt;mkdir         &lt;/span&gt;mkdirat       mkdtemp       mkdtempat_np
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And finally, an example of &lt;code&gt;bash&lt;/code&gt; auto-completing a command option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;python -&amp;lt;Tab&amp;gt;
-    &lt;span class="nt"&gt;-3&lt;/span&gt;   &lt;span class="nt"&gt;-B&lt;/span&gt;   &lt;span class="nt"&gt;-E&lt;/span&gt;   &lt;span class="nt"&gt;-O&lt;/span&gt;   &lt;span class="nt"&gt;-OO&lt;/span&gt;  &lt;span class="nt"&gt;-Q&lt;/span&gt;   &lt;span class="nt"&gt;-R&lt;/span&gt;   &lt;span class="nt"&gt;-S&lt;/span&gt;   &lt;span class="nt"&gt;-V&lt;/span&gt;   &lt;span class="nt"&gt;-W&lt;/span&gt;
&lt;span class="nt"&gt;-b&lt;/span&gt;   &lt;span class="nt"&gt;-c&lt;/span&gt;   &lt;span class="nt"&gt;-d&lt;/span&gt;   &lt;span class="nt"&gt;-h&lt;/span&gt;   &lt;span class="nt"&gt;-i&lt;/span&gt;   &lt;span class="nt"&gt;-m&lt;/span&gt;   &lt;span class="nt"&gt;-s&lt;/span&gt;   &lt;span class="nt"&gt;-t&lt;/span&gt;   &lt;span class="nt"&gt;-u&lt;/span&gt;   &lt;span class="nt"&gt;-v&lt;/span&gt;   &lt;span class="nt"&gt;-x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I suggest you get used to using auto-completion as much as possible. It&lt;br&gt;
can save you keystrokes, as well as make you discover command options&lt;br&gt;
you didn't know about.&lt;/p&gt;

&lt;p&gt;Pro-tip: if you are using bash, you can get install the&lt;br&gt;
&lt;code&gt;bash-completion&lt;/code&gt;&lt;sup id="fnref1"&gt;1&lt;/sup&gt; package (using your system package-manager) in&lt;br&gt;
order to enable auto-completion for a wide variety of commands that do&lt;br&gt;
not support it out-of-the-box.&lt;/p&gt;

&lt;p&gt;&lt;a id="keyboard-shortcuts"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Keyboard shortcuts
&lt;/h2&gt;

&lt;p&gt;The shell uses a library called &lt;code&gt;readline&lt;/code&gt;&lt;sup id="fnref2"&gt;2&lt;/sup&gt; to provide you with many&lt;br&gt;
keyboard shortcuts to navigate, edit, cut, paste, search, etc, in the&lt;br&gt;
command line. Mastering these will help to dramatically increase your&lt;br&gt;
efficiency, instead of copying and pasting with your mouse, and&lt;br&gt;
navigating the command with the ↑ and ↓ arrow&lt;br&gt;
keys.&lt;/p&gt;

&lt;p&gt;The default shortcuts are inspired by the &lt;code&gt;emacs&lt;/code&gt;&lt;sup id="fnref3"&gt;3&lt;/sup&gt; terminal-based&lt;br&gt;
text editor. If you are already familiar with it, a lot of the default&lt;br&gt;
&lt;code&gt;readline&lt;/code&gt; shortcuts might feel familiar. &lt;code&gt;emacs&lt;/code&gt; isn't the only famous&lt;br&gt;
text editor in the history of computers though: another one, dating back&lt;br&gt;
from 1976, is &lt;code&gt;vi&lt;/code&gt;.&lt;sup id="fnref4"&gt;4&lt;/sup&gt; &lt;code&gt;vi&lt;/code&gt; and &lt;code&gt;emacs&lt;/code&gt; are designed in two very&lt;br&gt;
different ways, and have two very different logics. It is possible that&lt;br&gt;
one might “click” more than the other for you. If you happen to be&lt;br&gt;
familiar with the &lt;code&gt;vi&lt;/code&gt; editor and are accustomed to its navigation&lt;br&gt;
system, you can replicate it in your shell as well by adding &lt;code&gt;set -o vi&lt;/code&gt;&lt;br&gt;
in your shell configuration file. If you are using &lt;code&gt;zsh&lt;/code&gt; with the Oh My&lt;br&gt;
Zsh framework that we introduced in the previous chapter, you can also&lt;br&gt;
use the &lt;code&gt;vi-mode&lt;/code&gt; plugin to do this.&lt;/p&gt;

&lt;p&gt;The advantage of using the same navigation logic and shortcuts in your&lt;br&gt;
text editor and your terminal is that is blurs the line between both,&lt;br&gt;
and brings consistency to your terminal environment. If you have no clue&lt;br&gt;
how &lt;code&gt;emacs&lt;/code&gt; or &lt;code&gt;vi&lt;/code&gt; work though, I would probably suggest you don't&lt;br&gt;
worry about all this for now and experiment with the default terminal&lt;br&gt;
shortcuts.&lt;/p&gt;
&lt;h3&gt;
  
  
  Navigating the current line
&lt;/h3&gt;

&lt;p&gt;The following navigation shortcuts allow you to move quickly your cursor&lt;br&gt;
in the current command saving you from relying solely on the&lt;br&gt;
→ and ← arrows.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Navigation&lt;/th&gt;
&lt;th&gt;Shortcut&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Go to beginning of line&lt;/td&gt;
&lt;td&gt;
Ctrl - A
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go to end of line&lt;/td&gt;
&lt;td&gt;
Ctrl - E
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go to next word&lt;/td&gt;
&lt;td&gt;
Alt - F
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go to previous word&lt;/td&gt;
&lt;td&gt;
Alt - B
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Toggle your cursor between its current position and the beginning of line&lt;/td&gt;
&lt;td&gt;
Ctrl - X - X
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you however prefer using the &lt;code&gt;vi&lt;/code&gt; navigation system, you will first&lt;br&gt;
need to type Esc to switch from the &lt;em&gt;Insertion&lt;/em&gt; mode to an&lt;br&gt;
emulation of &lt;code&gt;vi&lt;/code&gt;'s &lt;em&gt;normal&lt;/em&gt; mode, in which you can navigate in your&lt;br&gt;
text using the following shortcuts:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Navigation&lt;/th&gt;
&lt;th&gt;Shortcut&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Go to beginning of line&lt;/td&gt;
&lt;td&gt;^&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go to end of line&lt;/td&gt;
&lt;td&gt;$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go to next word&lt;/td&gt;
&lt;td&gt;w&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go to previous word&lt;/td&gt;
&lt;td&gt;b&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Move to the end of the previous word&lt;/td&gt;
&lt;td&gt;e&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You can go back to editing your command line by hitting the &lt;code&gt;i&lt;/code&gt; key.&lt;/p&gt;
&lt;h3&gt;
  
  
  Deleting and editing text
&lt;/h3&gt;

&lt;p&gt;These shortcuts allow you to quickly edit the current command more&lt;br&gt;
efficiently than by just using the Delete key.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Edition&lt;/th&gt;
&lt;th&gt;Shortcut&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Delete current character&lt;/td&gt;
&lt;td&gt;
Ctrl - D
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete previous word&lt;/td&gt;
&lt;td&gt;
Ctrl - W
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete next word&lt;/td&gt;
&lt;td&gt;
Alt - D
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edit the current command in your text editor&lt;/td&gt;
&lt;td&gt;
Ctrl - X Ctrl - E
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Undo previous action(s)&lt;/td&gt;
&lt;td&gt;
Ctrl - -
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The equivalent &lt;code&gt;vi&lt;/code&gt;-style shortcuts are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Edition&lt;/th&gt;
&lt;th&gt;Shortcut&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Replace current character by another (ex: &lt;em&gt;e&lt;/em&gt;)&lt;/td&gt;
&lt;td&gt;
r - e
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete current character&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete previous word&lt;/td&gt;
&lt;td&gt;
d - b
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete next word&lt;/td&gt;
&lt;td&gt;
d - w
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edit the current command in your text editor&lt;/td&gt;
&lt;td&gt;v&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Undo previous action(s)&lt;/td&gt;
&lt;td&gt;u&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Cutting and pasting
&lt;/h3&gt;

&lt;p&gt;The shell provides you with shortcuts to cut and paste commands quickly&lt;br&gt;
without using your mouse.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Shortcut&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cut current word before the cursor&lt;/td&gt;
&lt;td&gt;
Ctrl - W
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cut from cursor to end of line&lt;/td&gt;
&lt;td&gt;
Ctrl - K
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cut from cursor to start of line&lt;/td&gt;
&lt;td&gt;
Ctrl - U
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paste the cut buffer at current position&lt;/td&gt;
&lt;td&gt;
Ctrl - Y
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The equivalent &lt;code&gt;vi&lt;/code&gt;-style shortcuts are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Shortcut&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cut current word before the cursor&lt;/td&gt;
&lt;td&gt;
d - w
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cut from cursor to end of line&lt;/td&gt;
&lt;td&gt;
d - $
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cut from cursor to start of line&lt;/td&gt;
&lt;td&gt;
d - ^
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paste the cut buffer at current position&lt;/td&gt;
&lt;td&gt;p&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Controlling the terminal
&lt;/h3&gt;

&lt;p&gt;Finally, these shortcuts will let you interact with the terminal itself.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Shortcut&lt;/th&gt;
&lt;th&gt;Equivalent command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Clear the terminal screen&lt;/td&gt;
&lt;td&gt;
Ctrl - L
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;clear&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Close the terminal screen&lt;/td&gt;
&lt;td&gt;
Ctrl - D
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;exit&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Send current command to the background.&lt;/td&gt;
&lt;td&gt;
Ctrl - Z
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Even mastering &lt;em&gt;some&lt;/em&gt; of these shortcuts should make you immensely more&lt;br&gt;
productive at typing commands and navigating command-line interfaces. I&lt;br&gt;
suggest you take time to experiment until you feel more accustomed with&lt;br&gt;
them. I can guarantee that you will feel the productivity boost!&lt;/p&gt;
&lt;h3&gt;
  
  
  A unified command-line editing experience
&lt;/h3&gt;

&lt;p&gt;These shortcuts do not just work in your shell, but in any application&lt;br&gt;
using the &lt;code&gt;readline&lt;/code&gt; library to allow the user to type and edit&lt;br&gt;
commands. Learning these shortcuts will thus make you productive in all&lt;br&gt;
types of command lines that you might encounter in your career, such as&lt;br&gt;
&lt;code&gt;python&lt;/code&gt;, &lt;code&gt;irb&lt;/code&gt;, &lt;code&gt;sqlite3&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;To make sure you get a smooth and homogeneous editing experience in all&lt;br&gt;
command lines you use in your system, you can set your preferred mode in&lt;br&gt;
the &lt;code&gt;readline&lt;/code&gt; configuration file itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.inputrc
&lt;span class="nb"&gt;set &lt;/span&gt;editing-mode vi  &lt;span class="c"&gt;# or emacs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a id="navigating-through-history"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Navigating through history
&lt;/h2&gt;

&lt;p&gt;If you find yourself typing a certain command times and times again, you&lt;br&gt;
should probably be aware of how to navigate and search your shell&lt;br&gt;
history, in order to save time and keystrokes.&lt;/p&gt;

&lt;p&gt;While the obvious way to re-execute a previous command might seem to&lt;br&gt;
just bash on the ↑ key until you find the command you want,&lt;br&gt;
there are faster and smarter ways to accomplish this.&lt;/p&gt;
&lt;h3&gt;
  
  
  Searching the history
&lt;/h3&gt;

&lt;p&gt;A very useful and time-saving trick is searching for a command into your&lt;br&gt;
shell history instead of re-typing it from scratch. You can search your&lt;br&gt;
command history by typing Ctrl - R which opens a&lt;br&gt;
&lt;code&gt;reverse-i-search&lt;/code&gt; (backwards search) prompt, in which you can search&lt;br&gt;
for previously executed command containing a given search pattern.&lt;/p&gt;

&lt;p&gt;Type Ctrl - R to navigate through the results,&lt;br&gt;
until you find the one you were looking for and type the&lt;br&gt;
Enter key to execute it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&amp;lt;Ctrl-R&amp;gt;
&lt;span class="o"&gt;(&lt;/span&gt;reverse-i-search&lt;span class="o"&gt;)&lt;/span&gt;: &lt;span class="nb"&gt;echo&lt;/span&gt; &amp;lt;Ctrl-R&amp;gt; &amp;lt;Enter&amp;gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"hello world"&lt;/span&gt;
hello world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you want to stop the search, either hit&lt;br&gt;
Ctrl - C or Ctrl - G to be&lt;br&gt;
sent back into the regular shell prompt.&lt;/p&gt;

&lt;p&gt;History search works by looking into the shell history file&lt;br&gt;
(&lt;code&gt;~/.bash_history&lt;/code&gt; for &lt;code&gt;bash&lt;/code&gt; and &lt;code&gt;~/.zsh_history&lt;/code&gt; for &lt;code&gt;zsh&lt;/code&gt; by&lt;br&gt;
default). Every time you execute a command, it will be added to your&lt;br&gt;
shell history file (with a maximum number of retained commands defined&lt;br&gt;
by the &lt;code&gt;HISTSIZE&lt;/code&gt; environment variable).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The location of your shell history file can be configured by setting the&lt;br&gt;
&lt;code&gt;HISTFILE&lt;/code&gt; environment variable.&lt;/p&gt;
&lt;h3&gt;
  
  
  Rewriting history
&lt;/h3&gt;

&lt;p&gt;If you want to remove a sensitive command from your history, you can&lt;br&gt;
simply edit your &lt;code&gt;$HISTFILE&lt;/code&gt; history file and remove it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;secret-command &lt;span class="nt"&gt;--password&lt;/span&gt; 1234qwerty  &lt;span class="c"&gt;# oh no! that should not be in my history!&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep &lt;/span&gt;secret-command &lt;span class="nv"&gt;$HISTFILE&lt;/span&gt;
secret-command &lt;span class="nt"&gt;--password&lt;/span&gt; 1234qwerty
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'/secret-command/d'&lt;/span&gt; &lt;span class="nv"&gt;$HISTFILE&lt;/span&gt;  &lt;span class="c"&gt;# deletion of history line containing 'secret-command'&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep &lt;/span&gt;secret-command &lt;span class="nv"&gt;$HISTFILE&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="c"&gt;# it's not in history anymore&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can also use the &lt;code&gt;history&lt;/code&gt; built-in command to display your whole&lt;br&gt;
history&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;history&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 5
  496  &lt;span class="nb"&gt;mkdir test
  &lt;/span&gt;497  secret-command &lt;span class="nt"&gt;--password&lt;/span&gt; 1234qwerty
  498  &lt;span class="nb"&gt;cd
  &lt;/span&gt;499  man &lt;span class="nb"&gt;history
  &lt;/span&gt;500  &lt;span class="nb"&gt;history&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Each history line is prefixed by its index in the history. You can then&lt;br&gt;
use &lt;code&gt;history -d &amp;lt;index&amp;gt;&lt;/code&gt; to remove the associated line from history.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;history&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; 497
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;history&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 7
  496  &lt;span class="nb"&gt;mkdir test
  &lt;/span&gt;497  &lt;span class="nb"&gt;cd
  &lt;/span&gt;498  man &lt;span class="nb"&gt;history
  &lt;/span&gt;499  &lt;span class="nb"&gt;history&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 5
  500  &lt;span class="nb"&gt;history&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; 497
  501  &lt;span class="nb"&gt;history&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This only works with &lt;code&gt;bash&lt;/code&gt;, not &lt;code&gt;zsh&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Avoiding history
&lt;/h3&gt;

&lt;p&gt;There is a trick you can use if you want to fly under the radar and&lt;br&gt;
never have a command recorded in history in the first place. Simply&lt;br&gt;
prefix your command by a space.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you are using &lt;code&gt;zsh&lt;/code&gt;, you need to add &lt;code&gt;setopt HIST_IGNORE_SPACE&lt;/code&gt; in&lt;br&gt;
your &lt;code&gt;~/.zshrc&lt;/code&gt; to make sure that behavior is enabled.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt; secret-command &lt;span class="nt"&gt;--password&lt;/span&gt; 1234qwerty  &lt;span class="c"&gt;# notice the space at the start of the command!&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;history&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 2
  502  &lt;span class="nb"&gt;history&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 7
  503  &lt;span class="nb"&gt;history&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a id="shell-expansions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Shell expansions
&lt;/h2&gt;

&lt;p&gt;The shell can perform expansions, meaning it can replace portions of the&lt;br&gt;
command before executing it. Relying on expansions allows you to type&lt;br&gt;
less and rely on the shell itself to do the heavy lifting. While there&lt;br&gt;
are multiple types of expansions, we will only cover 5:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  history expansion: quickly access previous commands and arguments
from history&lt;/li&gt;
&lt;li&gt;  tilde expansion: replace the &lt;code&gt;~&lt;/code&gt; path prefix&lt;/li&gt;
&lt;li&gt;  pathname expansion: expand a path pattern into a list of files&lt;/li&gt;
&lt;li&gt;  braces expansion: expand a pattern between braces into a longer
sequence&lt;/li&gt;
&lt;li&gt;  command expansion: replace a sub-command by its output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Expansions are extremely powerful. When used right, an expansion can&lt;br&gt;
literally save you from writing a script.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: As we only over what we think are the most useful expansions and&lt;br&gt;
shortcuts, feel free to refer to the &lt;code&gt;bash&lt;/code&gt; manual, section &lt;code&gt;EXPANSION&lt;/code&gt;&lt;br&gt;
if you want to see the full list.&lt;/p&gt;
&lt;h3&gt;
  
  
  History expansion
&lt;/h3&gt;

&lt;p&gt;Your shell has multiple tricks in its sleeve to allow you to quickly&lt;br&gt;
reference previous commands or arguments in history with a minimum of&lt;br&gt;
keystrokes. While this section only provides you with what we feel are&lt;br&gt;
the most useful of them, feel free to go to the &lt;code&gt;HISTORY EXPANSION&lt;/code&gt;&lt;br&gt;
section of the &lt;code&gt;bash&lt;/code&gt; manual.&lt;/p&gt;
&lt;h4&gt;
  
  
  Event designators
&lt;/h4&gt;

&lt;p&gt;An &lt;em&gt;Event designator&lt;/em&gt; is a reference to a command line entry in the&lt;br&gt;
history list. It allows you to quickly refer to a previous command&lt;br&gt;
without having to re-type it.&lt;/p&gt;
&lt;h5&gt;
  
  
  &lt;code&gt;!-n&lt;/code&gt;
&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;!-n&lt;/code&gt; refers to the nth latest command: &lt;code&gt;!-1&lt;/code&gt; refers to the latest&lt;br&gt;
command, &lt;code&gt;!-2&lt;/code&gt; to the command before that, etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"hello world!"&lt;/span&gt;
hello world!
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nt"&gt;-2&lt;/span&gt;  &lt;span class="c"&gt;# !-1 is "cd" and !-2 is 'echo "hello world!"'&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"hello world"&lt;/span&gt;
hello world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;!!&lt;/code&gt; is a shortcut for &lt;code&gt;!-1&lt;/code&gt;, aka the latest command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"hello world!"&lt;/span&gt;
hello world!
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"hello world"&lt;/span&gt;
hello world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &lt;code&gt;!!&lt;/code&gt; is oftentimes used in conjunction with &lt;code&gt;sudo&lt;/code&gt;, to re-execute the&lt;br&gt;
previous command with superuser privileges when it failed, due to a lack&lt;br&gt;
of permission.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;vim /etc/myfile
vim: /etc/myfile: Permission denied
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vim /etc/myfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;code&gt;^string1^string2&lt;/code&gt;
&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;^string1^string2&lt;/code&gt; is used to repeat the previous command in which&lt;br&gt;
&lt;code&gt;string1&lt;/code&gt; is replaced by &lt;code&gt;string2&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ./myfile
Just a file full of junk
&lt;span class="nv"&gt;$ &lt;/span&gt;^cat^rm
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; ./myfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I personally use and abuse of this technique when I'm about to&lt;br&gt;
irremediably delete some resources (files, folders, containers, etc),&lt;br&gt;
and I want to make sure I'm about to delete the &lt;em&gt;right&lt;/em&gt; things by&lt;br&gt;
listing these resources first. If you are familiar with SQL queries, it&lt;br&gt;
is the equivalent of executing a &lt;code&gt;SELECT&lt;/code&gt; query before changing the&lt;br&gt;
&lt;code&gt;SELECT&lt;/code&gt; to &lt;code&gt;DELETE&lt;/code&gt; to make sure you're not going to delete more than&lt;br&gt;
you wanted to.&lt;/p&gt;
&lt;h4&gt;
  
  
  Word designators
&lt;/h4&gt;

&lt;p&gt;Word designators are used to select desired words from a previous&lt;br&gt;
command (by default, the latest). They can be very useful when you want&lt;br&gt;
to type a new command that uses arguments previously typed in a previous&lt;br&gt;
command.&lt;/p&gt;
&lt;h5&gt;
  
  
  &lt;code&gt;!^&lt;/code&gt;
&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;!^&lt;/code&gt; maps to the first argument of your latest command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;first.txt second.txt last.txt
&lt;span class="nv"&gt;$ &lt;/span&gt;vim &lt;span class="o"&gt;!&lt;/span&gt;^
&lt;span class="nv"&gt;$ &lt;/span&gt;vim first.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;code&gt;!$&lt;/code&gt;
&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;!$&lt;/code&gt; maps to the last argument of your latest command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;first.txt second.txt last.txt
&lt;span class="nv"&gt;$ &lt;/span&gt;vim &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;vim last.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h5&gt;
  
  
  Combining event and word designators
&lt;/h5&gt;

&lt;p&gt;You can even combine event and word designators in more complex shapes&lt;br&gt;
by using the following syntax&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[EVENT DESIGNATOR]:[WORD DESIGNATOR]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For example, you could use the &lt;code&gt;!!&lt;/code&gt; event designator to select the last&lt;br&gt;
command, and the &lt;code&gt;2&lt;/code&gt; word designator to select the second argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;first.txt second.txt last.txt
&lt;span class="nv"&gt;$ &lt;/span&gt;vim &lt;span class="o"&gt;!!&lt;/span&gt;:2
&lt;span class="nv"&gt;$ &lt;/span&gt;vim second.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Tilde expansion
&lt;/h3&gt;

&lt;p&gt;For each unquoted word starting with &lt;code&gt;~&lt;/code&gt; in the command, all characters&lt;br&gt;
preceding a forward slash (&lt;code&gt;/&lt;/code&gt;) will be considered a &lt;em&gt;tilde prefix&lt;/em&gt;.&lt;br&gt;
Depending on its actual value, the tilde prefix can be expanded several&lt;br&gt;
ways, although the simple &lt;code&gt;~&lt;/code&gt; is probably its most common use.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tilde prefix&lt;/th&gt;
&lt;th&gt;Expansion&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your home directory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~+&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your current working directory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your previous working directory&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; ~
Android                code       Downloads              Music
AndroidStudioProjects  Desktop    Dropbox                Pictures
bin                    Documents  Firefox_wallpaper.png  Videos
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This lists the content of your home directory, and is the equivalent to&lt;br&gt;
&lt;code&gt;ls $HOME&lt;/code&gt;. You can combine the tilde with a suffix to compose an&lt;br&gt;
absolute path to some file or folder in your home directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/code
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br/code
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Pathname expansion
&lt;/h3&gt;

&lt;p&gt;Pathname expansions allow you to write an short path pattern and have it&lt;br&gt;
expanded in a list of files and directories, saving you from tedious&lt;br&gt;
copy-pastes or a possibly long (and error-prone) command writing.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;code&gt;*&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The &lt;em&gt;glob&lt;/em&gt;, or &lt;em&gt;wildcard&lt;/em&gt; &lt;code&gt;*&lt;/code&gt; character matches any string. It allows&lt;br&gt;
you to give a &lt;em&gt;pattern&lt;/em&gt; to the shell, that it will then expand to all&lt;br&gt;
files and directories matching the pattern. The wildcard can be prefixed&lt;br&gt;
or suffixed, which will further specify our pattern. For example,&lt;br&gt;
&lt;code&gt;*.jpg&lt;/code&gt; matches all files ending with the &lt;code&gt;.jpg&lt;/code&gt; extension, and&lt;br&gt;
&lt;code&gt;README.*&lt;/code&gt; matches all files named &lt;code&gt;README&lt;/code&gt; whatever their extension.&lt;/p&gt;

&lt;p&gt;Let us consider the following file and directory structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree
&lt;span class="nb"&gt;.&lt;/span&gt;
|-- pic1.jpg
|-- pic2.jpg
|-- pic3.jpg
|-- pic4.jpg
&lt;span class="se"&gt;\_&lt;/span&gt;_ pics
|   |-- pic5.jpg
|   |-- pic6.jpg
|   &lt;span class="se"&gt;\_&lt;/span&gt;_ pic7.jpg
&lt;span class="se"&gt;\_&lt;/span&gt;_ sounds
    &lt;span class="se"&gt;\_&lt;/span&gt;_sound1.mp3

2 directory, 8 files
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We want to move all &lt;code&gt;jpg&lt;/code&gt; files into our &lt;code&gt;pics&lt;/code&gt; directory. Instead of&lt;br&gt;
running 4 different &lt;code&gt;mv&lt;/code&gt; commands or manually typing a long &lt;code&gt;mv&lt;/code&gt;&lt;br&gt;
command, we can run just one using a pathname expansion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mv&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.jpg pics
&lt;span class="nv"&gt;$ &lt;/span&gt;tree
&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="se"&gt;\_&lt;/span&gt;_ pics
|   |-- pic1.jpg
|   |-- pic2.jpg
|   |-- pic3.jpg
|   |-- pic4.jpg
|   |-- pic5.jpg
|   |-- pic6.jpg
|   &lt;span class="se"&gt;\_&lt;/span&gt;_ pic7.jpg
&lt;span class="se"&gt;\_&lt;/span&gt;_ sounds
    &lt;span class="se"&gt;\_&lt;/span&gt;_sound1.mp3

2 directory, 8 files
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;*.jpg&lt;/code&gt; was expanded to all files ending with &lt;code&gt;.jpg&lt;/code&gt;, causing the shell&lt;br&gt;
to actually run &lt;code&gt;mv pic1.jpg pic2.jpg pic3.jpg pic4.jpg pics&lt;/code&gt;, causing&lt;br&gt;
all 4 &lt;code&gt;jpg&lt;/code&gt; files to be moved to the &lt;code&gt;pics&lt;/code&gt; directory in a single&lt;br&gt;
command.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: We could have executed the following commands for the same result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;mv pic* pics&lt;/code&gt; would have moved all files with name starting by
&lt;code&gt;pic&lt;/code&gt; to the &lt;code&gt;pics&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;mv pic*.jpg pics&lt;/code&gt; would have moved all files with name starting by
&lt;code&gt;pic&lt;/code&gt; and ending with &lt;code&gt;.jpg&lt;/code&gt; to the &lt;code&gt;pics&lt;/code&gt; directory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can use &lt;code&gt;*&lt;/code&gt; several times within the same pattern. For example&lt;br&gt;
&lt;code&gt;ls */*&lt;/code&gt; will list all files and directories located in a subdirectory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;
sounds/sound1.mp3   pics/pic2.jpg       pics/pic4.jpg       pics/pic6.jpg
pics/pic1.jpg       pics/pic3.jpg       pics/pic5.jpg       pics/pic7.jpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Like in our second example, we can also use &lt;code&gt;*/*.jpg&lt;/code&gt; to list all &lt;code&gt;jpg&lt;/code&gt;&lt;br&gt;
files located in a subdirectory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.jpg
pics/pic1.jpg   pics/pic3.jpg   pics/pic5.jpg  pics/pic7.jpg
pics/pic2.jpg   pics/pic4.jpg   pics/pic6.jpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;**&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;**&lt;/code&gt; is expanded to all files and directories in the children&lt;br&gt;
directories, with a depth limit of 1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;README.txt
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;sounds/lyrics
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;sounds/lyrics/sound1.txt
&lt;span class="nv"&gt;$ &lt;/span&gt;tree
&lt;span class="nb"&gt;.&lt;/span&gt;
|-- README.txt
&lt;span class="se"&gt;\_&lt;/span&gt;_ pics
|   |-- pic1.jpg
|   |-- pic2.jpg
|   |-- pic3.jpg
|   |-- pic4.jpg
|   |-- pic5.jpg
|   |-- pic6.jpg
|   &lt;span class="se"&gt;\_&lt;/span&gt;_ pic7.jpg
&lt;span class="se"&gt;\_&lt;/span&gt;_ sounds
    &lt;span class="se"&gt;\_&lt;/span&gt;_ lyrics
    |   &lt;span class="se"&gt;\_&lt;/span&gt;_sound1.txt
    &lt;span class="se"&gt;\_&lt;/span&gt;_sound1.mp3

3 directories, 10 files
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="k"&gt;**&lt;/span&gt;
README.txt

pics:
pic1.jpg pic2.jpg pic3.jpg pic4.jpg pic5.jpg pic6.jpg pic7.jpg

sounds:
lyrics     sounds.mp3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ls **&lt;/code&gt; was expanded into &lt;code&gt;ls README.txt pics/ sounds/&lt;/code&gt;, which does not&lt;br&gt;
include the content of &lt;code&gt;sounds/lyrics&lt;/code&gt; because of the depth limit of 1.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;code&gt;**/&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;**/&lt;/code&gt; is expanded into all directories and subdirectories with a depth&lt;br&gt;
limit of 1 starting from our first directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree
&lt;span class="nb"&gt;.&lt;/span&gt;
|-- README.txt
&lt;span class="se"&gt;\_&lt;/span&gt;_ pics
|   |-- pic1.jpg
|   |-- pic2.jpg
|   |-- pic3.jpg
|   |-- pic4.jpg
|   |-- pic5.jpg
|   |-- pic6.jpg
|   &lt;span class="se"&gt;\_&lt;/span&gt;_ pic7.jpg
&lt;span class="se"&gt;\_&lt;/span&gt;_ sounds
    &lt;span class="se"&gt;\_&lt;/span&gt;_ lyrics
    |   &lt;span class="se"&gt;\_&lt;/span&gt;_sound1.txt
    &lt;span class="se"&gt;\_&lt;/span&gt;_sound1.mp3


3 directories, 10 files
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="k"&gt;**&lt;/span&gt;/
pics/:
pic1.jpg pic2.jpg pic3.jpg pic4.jpg pic5.jpg pic6.jpg pic7.jpg

sounds/:
lyrics     sounds.mp3

sounds/lyrics/:
sound1.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ls **/&lt;/code&gt; was expanded into &lt;code&gt;ls sounds/ sounds/lyrics pics/&lt;/code&gt;. It thus&lt;br&gt;
listed all files located in our subdirectories.&lt;/p&gt;
&lt;h3&gt;
  
  
  Brace expansion
&lt;/h3&gt;

&lt;p&gt;A brace expansion is a mechanism by which the shell can generate&lt;br&gt;
multiple strings based on a sequence of tokens defined within curly&lt;br&gt;
braces. The brace expansion pattern can be preceded by an optional&lt;br&gt;
&lt;em&gt;preamble&lt;/em&gt; and followed by an optional &lt;em&gt;postscript&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/test/&lt;span class="o"&gt;{&lt;/span&gt;pics,sounds,sprites&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; ~/test
pics  sounds  sprites
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;~/test/{pics,sounds,sprites}&lt;/code&gt; was expanded into&lt;br&gt;
&lt;code&gt;~/test/pics ~/test/sounds ~/test/sprites&lt;/code&gt; causing the shell to execute&lt;br&gt;
&lt;code&gt;mkdir ~/test/pics ~/test/sounds ~/test/sprites&lt;/code&gt; (which will be expanded&lt;br&gt;
further into&lt;br&gt;
&lt;code&gt;mkdir /home/br/test/pics /home/br/test/sounds /home/br/test/sprites&lt;/code&gt; by&lt;br&gt;
a tilde expansion).&lt;/p&gt;

&lt;p&gt;We could have done the same thing by factoring the final &lt;code&gt;s&lt;/code&gt; of each&lt;br&gt;
token into a postscript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/test/&lt;span class="o"&gt;{&lt;/span&gt;pic,sound,sprite&lt;span class="o"&gt;}&lt;/span&gt;s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;A brace expansion can also have a sequence pattern &lt;code&gt;{x..y[..incr]}&lt;/code&gt;&lt;br&gt;
where &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; are either an integer or a single character, and&lt;br&gt;
&lt;code&gt;incr&lt;/code&gt; is an optional increment value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; ~/test/sounds/noise-&lt;span class="o"&gt;{&lt;/span&gt;1..5&lt;span class="o"&gt;}&lt;/span&gt;.mp3
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; ~/test/sounds
noise-1.mp3 noise-2.mp3 noise-3.mp3 noise-4.mp3 noise-5.mp3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The default increment is 1 if the sequence end is greater than its&lt;br&gt;
start, and -1 otherwise. However, we could specify a custom increment&lt;br&gt;
value if we want.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; ~/test/pics/pic&lt;span class="o"&gt;{&lt;/span&gt;1..10..2&lt;span class="o"&gt;}&lt;/span&gt;.jpg
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; ~/test/pics
pic1.jpg pic3.jpg pic5.jpg pic7.jpg pic9.jpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Command expansion
&lt;/h3&gt;

&lt;p&gt;Your shell can replace a command surrounded by &lt;code&gt;$()&lt;/code&gt; with its output.&lt;/p&gt;

&lt;p&gt;I personally like use to commands expansions can to iterate over a&lt;br&gt;
command's result, or by combining it with a heredoc redirection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt; aboutme
My name is &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;whoami&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;
and I live in &lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="sh"&gt;
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;aboutme
My name is br
and I live &lt;span class="k"&gt;in&lt;/span&gt; /home/br
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a id="real-life-examples"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-life examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Moving a pattern of files contained in directories and subdirectories
&lt;/h3&gt;

&lt;p&gt;What is really powerful with these expansions is that, like almost&lt;br&gt;
everything in the shell, they can be combined. The following example&lt;br&gt;
combines a pathname expansion, a brace expansion and a tilde expansion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree
&lt;span class="nb"&gt;.&lt;/span&gt;
|-- README.txt
&lt;span class="se"&gt;\_&lt;/span&gt;_ pics
|   |-- pic1.jpg
|   |-- pic2.jpg
|   |-- pic3.jpg
|   |-- pic4.jpg
|   |-- pic5.jpg
|   |-- pic6.jpg
|   &lt;span class="se"&gt;\_&lt;/span&gt;_ pic7.jpg
&lt;span class="se"&gt;\_&lt;/span&gt;_ sounds
    &lt;span class="se"&gt;\_&lt;/span&gt;_ lyrics
    |   &lt;span class="se"&gt;\_&lt;/span&gt;_sound1.txt
    &lt;span class="se"&gt;\_&lt;/span&gt;_sound1.mp3
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mv&lt;/span&gt; &lt;span class="k"&gt;**&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.&lt;span class="o"&gt;{&lt;/span&gt;jpg,mp3&lt;span class="o"&gt;}&lt;/span&gt; ~/assets/
&lt;span class="nv"&gt;$ &lt;/span&gt;tree
|-- README.txt
&lt;span class="se"&gt;\_&lt;/span&gt;_ pics
&lt;span class="se"&gt;\_&lt;/span&gt;_ sounds
    &lt;span class="se"&gt;\_&lt;/span&gt;_ lyrics
        &lt;span class="se"&gt;\_&lt;/span&gt;_sound1.txt
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; ~/assets
README.txt pic1.jpg   pic2.jpg   pic3.jpg   pic4.jpg   pic5.jpg   pic6.jpg   pic7.jpg   sound1.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Using these expansions, we were able to move all &lt;code&gt;jpg&lt;/code&gt; and &lt;code&gt;mp3&lt;/code&gt; files&lt;br&gt;
located in directories and subdirectories to the &lt;code&gt;assets&lt;/code&gt; directory&lt;br&gt;
located in your home directory, in exactly 27 characters!&lt;/p&gt;
&lt;h3&gt;
  
  
  Renaming multiple directories
&lt;/h3&gt;

&lt;p&gt;We could use a &lt;code&gt;for&lt;/code&gt; loop, pathname expansion and a command expansion to&lt;br&gt;
rename all directories contained in the bcurrent directory to their&lt;br&gt;
uppercase equivalent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="nb"&gt;dir &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;mv&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$dir&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'[:lower:]'&lt;/span&gt; &lt;span class="s1"&gt;'[:upper:]'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's decompose that command into its different steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  the &lt;code&gt;*/&lt;/code&gt; glob pattern is expanded over the list of
directories, on which we iterate via a &lt;code&gt;for&lt;/code&gt; loop&lt;/li&gt;
&lt;li&gt;  we execute &lt;code&gt;echo $dir | tr '[:lower:]' '[:upper:]'&lt;/code&gt;, which will
convert the current directory name to uppercase&lt;/li&gt;
&lt;li&gt;  the &lt;code&gt;$(echo $dir | tr '[:lower:]' '[:upper:]')&lt;/code&gt; command is expanded
into the uppercase directory name&lt;/li&gt;
&lt;li&gt;  the directory is renamed into an uppercase name&lt;/li&gt;
&lt;li&gt;  the &lt;code&gt;for&lt;/code&gt; loop iterates over the next directory name&lt;/li&gt;
&lt;li&gt;  we move on to the next directory and repeat the previous steps for
each of them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Iterating over paths with a &lt;code&gt;for&lt;/code&gt; loop is brittle as it breaks if a path&lt;br&gt;
contains a space. We will later see how to properly do it using the&lt;br&gt;
&lt;code&gt;find&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;&lt;a id="summary"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Your shell has so many productivity tricks and shortcuts up its sleeve&lt;br&gt;
it can be a little bit daunting. I suggest you don't try to learn them&lt;br&gt;
all at once, but really just experiment with them and see what feels&lt;br&gt;
natural. Even mastering some of them will make you more productive!&lt;/p&gt;

&lt;p&gt;What if there is an action you find useful but you just don't like the&lt;br&gt;
keyboard shortcut? Luckily for you, the next chapter will dive into how&lt;br&gt;
to personalize and customize your shell.&lt;/p&gt;

&lt;p&gt;&lt;a id="going-further"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Going further
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;5.1&lt;/strong&gt;: Create a directory. Use a bash expansion to move into that&lt;br&gt;
directory without typing its name a second time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.2&lt;/strong&gt;: Print your 4th last command typed into your terminal without&lt;br&gt;
re-typing it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.3&lt;/strong&gt;: Create the following empty files &lt;code&gt;README.txt&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;requirements.txt&lt;/code&gt; and &lt;code&gt;TODO.txt&lt;/code&gt; in a single command, without typing&lt;br&gt;
&lt;code&gt;.txt&lt;/code&gt; more than once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.4&lt;/strong&gt;: Delete all the files created in the last question without&lt;br&gt;
typing &lt;code&gt;.txt&lt;/code&gt; more than once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.5&lt;/strong&gt;: Create the following directory tree in a single command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;files
|-- 1
|   |-- 1a
|   |-- 1b
|   |-- 1c
|   |-- 2a
|   |-- 2b
|   |-- 2c
|   |-- 3a
|   |-- 3b
|   &lt;span class="se"&gt;\-&lt;/span&gt;- 3c
|-- 2
|   |-- 1a
|   |-- 1b
|   |-- 1c
|   |-- 2a
|   |-- 2b
|   |-- 2c
|   |-- 3a
|   |-- 3b
|   &lt;span class="se"&gt;\-&lt;/span&gt;- 3c
&lt;span class="se"&gt;\-&lt;/span&gt;- 3
    |-- 1a
    |-- 1b
    |-- 1c
    |-- 2a
    |-- 2b
    |-- 2c
    |-- 3a
    |-- 3b
    &lt;span class="se"&gt;\-&lt;/span&gt;- 3c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5.6&lt;/strong&gt;: Remove all subdirectories starting with &lt;code&gt;3&lt;/code&gt; created in the&lt;br&gt;
previous command, while keeping the top &lt;code&gt;3&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.7&lt;/strong&gt;: Re-execute the command from exercise 5.3 by looking backwards&lt;br&gt;
into your shell history.&lt;/p&gt;


&lt;p&gt;
&lt;em&gt;Essential Tools and Practices for the Aspiring Software Developer&lt;/em&gt; is a self-published book project by Balthazar Rouberol and &lt;a href="https://etnbrd.com"&gt;Etienne Brodu&lt;/a&gt;, ex-roommates, friends and colleagues, aiming at empowering the up and coming generation of developers. We currently are hard at work on it!
&lt;/p&gt;

&lt;p&gt;The book will help you set up a productive development environment and get acquainted with tools and practices that, along with your programming languages of choice, will go a long way in helping you grow as a software developer.
  It will cover subjects such as mastering the terminal, configuring and getting productive in a shell, the basics of code versioning with &lt;code&gt;git&lt;/code&gt;, SQL basics, tools such as &lt;code&gt;Make&lt;/code&gt;, &lt;code&gt;jq&lt;/code&gt; and regular expressions, networking basics as well as software engineering and collaboration best practices.
&lt;/p&gt;

&lt;p&gt;
  If you are interested in the project, we invite you to join the &lt;a href="https://balthazar-rouberol.us4.list-manage.com/subscribe?u=1f6080d496af07a836270ff1d&amp;amp;id=81ebd36adb"&gt;mailing list&lt;/a&gt;!
&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://github.com/scop/bash-completion"&gt;https://github.com/scop/bash-completion&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;&lt;a href="https://tiswww.case.edu/php/chet/readline/rltop.html"&gt;https://tiswww.case.edu/php/chet/readline/rltop.html&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;&lt;a href="https://www.gnu.org/software/emacs/"&gt;https://www.gnu.org/software/emacs/&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Vi"&gt;https://en.wikipedia.org/wiki/Vi&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>linux</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>bash</category>
    </item>
    <item>
      <title>Customizing your shell</title>
      <dc:creator>Balthazar Rouberol</dc:creator>
      <pubDate>Fri, 17 Apr 2020 09:45:41 +0000</pubDate>
      <link>https://dev.to/brouberol/customizing-your-shell-31hf</link>
      <guid>https://dev.to/brouberol/customizing-your-shell-31hf</guid>
      <description>&lt;p&gt;Originally posted on my &lt;a href="https://blog.balthazar-rouberol.com/customizing-your-shell" rel="noopener noreferrer"&gt;blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;
    This article is part of a self-published book project by Balthazar Rouberol and &lt;a href="https://etnbrd.com" rel="noopener noreferrer"&gt;Etienne Brodu&lt;/a&gt;, ex-roommates, friends and colleagues, aiming at empowering the up and coming generation of developers. We currently are hard at work on it!
&lt;/p&gt;

&lt;p&gt;
  If you are interested in the project, we invite you to join the &lt;a href="https://balthazar-rouberol.us4.list-manage.com/subscribe?u=1f6080d496af07a836270ff1d&amp;amp;id=81ebd36adb" rel="noopener noreferrer"&gt;mailing list&lt;/a&gt;!
&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Which terminal should I use?&lt;/li&gt;
&lt;li&gt;What font should I use?&lt;/li&gt;
&lt;li&gt;What shell should I use?&lt;/li&gt;
&lt;li&gt;Configuring your shell&lt;/li&gt;
&lt;li&gt;Configuring your prompt&lt;/li&gt;
&lt;li&gt;Shell configuration frameworks&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;li&gt;Going further&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Customizing your shell
&lt;/h1&gt;

&lt;p&gt;It is very common for programmers to tweak and customize their terminal&lt;br&gt;
and shell for hours, add or write new plug-ins, all in pursuit of the&lt;br&gt;
“perfect environment” and an increase of productivity. Others, on the&lt;br&gt;
contrary, avoid tweaking their shell altogether in order to always get&lt;br&gt;
the same experience on every machine.&lt;/p&gt;

&lt;p&gt;On a personal note, I tend to favor having a personalized shell as much&lt;br&gt;
as possible. I feel that sharing files between different computers is&lt;br&gt;
now a solved issue, and the benefits I get from having personalized my&lt;br&gt;
work environments are so great that I gladly pay the small price of&lt;br&gt;
synchronizing that configuration between my computers.&lt;/p&gt;

&lt;p&gt;In that chapter, we will learn more about the shell and how to configure&lt;br&gt;
your terminal environment to make it work &lt;em&gt;for&lt;/em&gt; you. Please note that&lt;br&gt;
some of the recommendations come from personal taste, and might not work&lt;br&gt;
for you nor suit you. We encourage you to explore and find what feels&lt;br&gt;
right, but we hope to at least nudge you in the right direction.&lt;/p&gt;

&lt;p&gt;&lt;a id="which-terminal-should-i-use"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Which terminal should I use?
&lt;/h2&gt;

&lt;p&gt;First off, if you are new to using the terminal, you might not have&lt;br&gt;
realized that it exists &lt;em&gt;multiple&lt;/em&gt; terminal applications. MacOS comes&lt;br&gt;
with Terminal pre-installed, and most Linux distributions come with&lt;br&gt;
either xterm, Gnome-terminal or Konsole pre-installed, and there is a&lt;br&gt;
vast number of available alternatives.&lt;/p&gt;

&lt;p&gt;I don't think there is a good, absolute and definitive answer when it&lt;br&gt;
comes to picking the “right” terminal application. You might get various&lt;br&gt;
answers depending who you ask. That being said, I can at least mention&lt;br&gt;
my own personal recommendations and preferences.&lt;/p&gt;

&lt;p&gt;Whatever terminal you end up using, I think that it is really important&lt;br&gt;
you configure it to your liking and preferences. As a programmer, you&lt;br&gt;
will probably spend a great deal of time in your terminal, and for you&lt;br&gt;
to feel productive and empowered, it needs to work &lt;em&gt;for&lt;/em&gt; you.&lt;/p&gt;
&lt;h3&gt;
  
  
  Terminator
&lt;/h3&gt;

&lt;p&gt;If you are running Linux, I personally favor Terminator&lt;sup id="fnref1"&gt;1&lt;/sup&gt; over the&lt;br&gt;
default choices. It has several features I find useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  a tab system, allowing you to have multiple tab of terminal(s)
within the same window&lt;/li&gt;
&lt;li&gt;  a grid system, allowing you to have multiple terminals in the same
tab&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fterminator.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fterminator.png" alt="I can work in multiple panes within the same tab, and have one tab per project"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;I can work in multiple panes within the same tab, and have one tab per project&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Here are the terminator keyboard shortcuts I find the most useful:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Shortcut&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
Ctrl - Shift - E
&lt;/td&gt;
&lt;td&gt;split the screen vertically&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
Ctrl - Shift - O
&lt;/td&gt;
&lt;td&gt;split the screen horizontally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
Ctrl - Shift - T
&lt;/td&gt;
&lt;td&gt;open a new tab&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
Ctrl - PageUp
&lt;/td&gt;
&lt;td&gt;switch to the next tab&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
Ctrl - PageDown
&lt;/td&gt;
&lt;td&gt;switch to the previous tab&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
Ctrl - N
&lt;/td&gt;
&lt;td&gt;open a new window&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
Ctrl - Shift - +
&lt;/td&gt;
&lt;td&gt;zoom in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
Ctrl - Shift - -
&lt;/td&gt;
&lt;td&gt;zoom out&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
Ctrl - D
&lt;/td&gt;
&lt;td&gt;close the current terminal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  iTerm2
&lt;/h3&gt;

&lt;p&gt;As far as macOS is concerned, I find the default terminal (plainly named&lt;br&gt;
Terminal) to be hard to use. The terminal that seems to be widely&lt;br&gt;
accepted by the macOS programming community is iTerm2&lt;sup id="fnref2"&gt;2&lt;/sup&gt;. It has all of&lt;br&gt;
the features cited above, and many (many) more!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fiterm2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fiterm2.png" alt="iTerm2 looks similar to Terminator but can do much, much more"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;iTerm2 looks similar to Terminator but can do much, much more&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;The iTerm2 keyboard shortcuts I find the most useful are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Shortcut&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
Cmd - D
&lt;/td&gt;
&lt;td&gt;split the screen vertically&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
Cmd - Shift - D
&lt;/td&gt;
&lt;td&gt;split the screen horizontally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
Cmd - T
&lt;/td&gt;
&lt;td&gt;open a new tab&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
Cmd - Shift - +
&lt;/td&gt;
&lt;td&gt;zoom in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
Cmd - Shift - -
&lt;/td&gt;
&lt;td&gt;zoom out&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
Cmd - N
&lt;/td&gt;
&lt;td&gt;open a new window&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
Cmd - D
&lt;/td&gt;
&lt;td&gt;close the current terminal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The following sections go over some non-default iTerm2 settings that I&lt;br&gt;
find convenient. Again, these are my preference and are in no way&lt;br&gt;
prescriptive. Feel free to discard them if you want.&lt;/p&gt;
&lt;h4&gt;
  
  
  Open file shortcut
&lt;/h4&gt;

&lt;p&gt;One of the iTerm2 features I enjoy is the ability of using&lt;br&gt;
Cmd + mouse click on a file path or an URL, to open the&lt;br&gt;
resource with the default associated program. For example, it will open&lt;br&gt;
an URL in your browser, a path to a local PDF file with Preview, a text&lt;br&gt;
file with your preferred text editor, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fiterm2-pointer-pref.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fiterm2-pointer-pref.png" alt="By enabling this feature, you will be able to open a file using a graphical application from your terminal"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;By enabling this feature, you will be able to open a file using a graphical application from your terminal&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Intuitive location for new terminals
&lt;/h4&gt;

&lt;p&gt;Another tweak I've done to iTerm2 was changing the working directory new&lt;br&gt;
terminals will open into by default. What I wanted was&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  open a new terminal window in my home directory&lt;/li&gt;
&lt;li&gt;  open a new terminal tab in my home directory&lt;/li&gt;
&lt;li&gt;  open a new terminal split pane in the previous session's directory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I did this because I oftentimes found myself splitting the current tab&lt;br&gt;
when I want to run multiple commands within the same project, and I had&lt;br&gt;
to &lt;code&gt;cd&lt;/code&gt; into the project directory every time I did a pane split.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fiterm2-advanced-pref.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fiterm2-advanced-pref.png" alt="I reduced the time I spent  raw `cd` endraw -ing into project directories with these settings. Preferences \&amp;gt; Profiles \&amp;gt; General \&amp;gt; Working Directory \&amp;gt; Advanced Configuration \&amp;gt; Edit"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;I reduced the time I spent &lt;code&gt;cd&lt;/code&gt;-ing into project directories with these settings. Preferences &amp;gt; Profiles &amp;gt; General &amp;gt; Working Directory &amp;gt; Advanced Configuration &amp;gt; Edit&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="what-font-should-i-use"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What font should I use?
&lt;/h2&gt;

&lt;p&gt;Using a font you enjoy is paramount. If you spend a lot of time reading&lt;br&gt;
and writing in your terminal, you might as well do it using a font that&lt;br&gt;
feels right to you.&lt;/p&gt;

&lt;p&gt;I personally really enjoy the Fira Code&lt;sup id="fnref3"&gt;3&lt;/sup&gt; font, both in my text editor&lt;br&gt;
and my terminal. Not only does it look really nice on the eye, but it&lt;br&gt;
also contains a set of &lt;em&gt;ligatures&lt;/em&gt; for multi character combinations,&lt;br&gt;
such as &lt;code&gt;!&lt;/code&gt; and &lt;code&gt;=&lt;/code&gt; rendered in a single character, allowing you to read&lt;br&gt;
code and decode symbols more easily.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fligature-code-example.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fligature-code-example.png" alt="Example of rendered character ligatures"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;Example of rendered character ligatures&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Note that not all terminals support fonts with ligatures. For example,&lt;br&gt;
iTerm2 does but Terminator does not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; While Fira Code has my preference, there are other well-designed fonts&lt;br&gt;
including ligatures, such as JetBrains Mono.&lt;sup id="fnref4"&gt;4&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="what-shell-should-i-use"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What shell should I use?
&lt;/h2&gt;

&lt;p&gt;We have hinted at it until now: &lt;code&gt;bash&lt;/code&gt; is not the only shell out there.&lt;br&gt;
You are free to use other shells if you want, such as &lt;code&gt;zsh&lt;/code&gt;, &lt;code&gt;fish&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;nushell&lt;/code&gt;, … As it was the case with terminals, the “good” terminal&lt;br&gt;
really depends on your definition of “good”. If you deeply care about&lt;br&gt;
using the same shell on every machine you work on, then &lt;code&gt;bash&lt;/code&gt; is&lt;br&gt;
possibly for you. It has been around since 1989, is stable, mature and&lt;br&gt;
is the default shell on almost&lt;sup id="fnref5"&gt;5&lt;/sup&gt; every UNIX system out there.&lt;/p&gt;

&lt;p&gt;When researching this book, I was surprised to learn that &lt;code&gt;zsh&lt;/code&gt; (or the&lt;br&gt;
Z-shell) wasn't really the last “kid on the block” either, as it was&lt;br&gt;
first released in 1990, just a year after the first stable bash release!&lt;br&gt;
You can expect the same level of stability, maturity and even syntax (to&lt;br&gt;
a large extent, except when it comes to configuration) than bash.&lt;/p&gt;

&lt;p&gt;I personally think &lt;code&gt;zsh&lt;/code&gt; really shines by providing a powerful default&lt;br&gt;
auto-completion experience, as well as more configuration options. As&lt;br&gt;
&lt;code&gt;zsh&lt;/code&gt; is compatible with &lt;code&gt;bash&lt;/code&gt;'s own syntax, I encourage you to try&lt;br&gt;
them until you feel comfortable with one or the other.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;fish&lt;/code&gt;&lt;sup id="fnref6"&gt;6&lt;/sup&gt; shell takes a radical turn from &lt;code&gt;bash&lt;/code&gt; or &lt;code&gt;zsh&lt;/code&gt; by&lt;br&gt;
providing an incompatible but “simple and clean” syntax, an extremely&lt;br&gt;
powerful command suggestion system, and an interactive configuration&lt;br&gt;
wizard.&lt;/p&gt;

&lt;p&gt;If you are getting started with using the shell, my personal&lt;br&gt;
recommendation is to stick to &lt;code&gt;bash&lt;/code&gt; or &lt;code&gt;zsh&lt;/code&gt; and experiment with other&lt;br&gt;
shells to see what value they bring once you feel more confident.&lt;/p&gt;
&lt;h3&gt;
  
  
  Changing your default shell
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;chsh&lt;/code&gt; (standing for &lt;em&gt;change shell&lt;/em&gt;) command allows you to change&lt;br&gt;
your default shell.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Switching to bash by default&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;chsh &lt;span class="nt"&gt;-s&lt;/span&gt; /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Switching to zsh by default&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;chsh &lt;span class="nt"&gt;-s&lt;/span&gt; /bin/zsh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have run &lt;code&gt;chsh&lt;/code&gt;, any new terminal window you open will run your&lt;br&gt;
new default shell.&lt;/p&gt;

&lt;p&gt;&lt;a id="configuring-your-shell"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuring your shell
&lt;/h2&gt;

&lt;p&gt;Up until now, every example we have seen have defined environment&lt;br&gt;
variables, aliases and functions directly in the shell. However, if we&lt;br&gt;
closed that shell, all of these changes would be undone and we would&lt;br&gt;
have to start again the next time we open a new one. Fortunately, all of&lt;br&gt;
these settings can be persisted in a &lt;em&gt;configuration file&lt;/em&gt;. Adding&lt;br&gt;
aliases, environment variables and functions to that file will make sure&lt;br&gt;
they get imported every time you open a new shell.&lt;/p&gt;

&lt;p&gt;These files usually reside in your home directory, and are named&lt;br&gt;
&lt;code&gt;.bashrc&lt;/code&gt; for bash, and &lt;code&gt;.zshrc&lt;/code&gt; for zsh.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.zshrc
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;EDITOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;vim
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/bin

&lt;span class="nb"&gt;alias ls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ls -G'&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt; ..&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'cd ..'&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt; ...&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'cd ../..'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;filesize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ls --size --human-readable -1'&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;mkcd &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
    &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$target&lt;/span&gt;
    &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$target&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After adding anything to your shell configuration file, you need to run&lt;br&gt;
&lt;code&gt;source ~/.zshrc&lt;/code&gt; (or &lt;code&gt;source ~/.bashrc&lt;/code&gt;, depending on your shell). The&lt;br&gt;
&lt;code&gt;source&lt;/code&gt; built-in command reads and executes commands from the argument&lt;br&gt;
file name in the current shell environment. Said in another way, running&lt;br&gt;
&lt;code&gt;source ~/.&amp;lt;file&amp;gt;&lt;/code&gt; will cause the shell to reload its configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; &lt;code&gt;rc&lt;/code&gt; stands for &lt;em&gt;run commands&lt;/em&gt;. Indeed, when you &lt;code&gt;source&lt;/code&gt; your&lt;br&gt;
configuration file, you will run the commands it contains. The subtlety&lt;br&gt;
with &lt;code&gt;source&lt;/code&gt; is that it executes the argument script within your&lt;br&gt;
&lt;em&gt;current&lt;/em&gt; shell, meaning any sourced commands will have a side-effect on&lt;br&gt;
your running shell.&lt;/p&gt;

&lt;p&gt;If you can never remember a given command's options, or if you always&lt;br&gt;
find yourself typing a group of commands, I encourage you to define&lt;br&gt;
aliases and functions in your shell configuration file. They will allow&lt;br&gt;
you to feel more productive day after day, especially so if the alias&lt;br&gt;
and tools are abstracting complex commands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; The previous chapter ended with some real-life examples of alias and&lt;br&gt;
functions. Feel free to add them to your shell configuration file.&lt;/p&gt;

&lt;p&gt;&lt;a id="configuring-your-prompt"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuring your prompt
&lt;/h2&gt;

&lt;p&gt;Configuring your &lt;span&gt;prompt&lt;/span&gt; is a very&lt;br&gt;
good way to make the shell work for you as much as possible, by&lt;br&gt;
providing you with useful context, such as the time of day, whether the&lt;br&gt;
last command was successful, your current working directory… While they&lt;br&gt;
can provide context and information to you, they will carry that context&lt;br&gt;
to anyone you copy and paste a command and associated output to.&lt;/p&gt;

&lt;p&gt;Configuring your prompt is done by changing the value of the &lt;code&gt;PS1&lt;/code&gt;&lt;br&gt;
environment variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PS1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"MY COOL PROMPT $"&lt;/span&gt;
MY COOL PROMPT &lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I think we can agree that &lt;code&gt;MY COOL PROMPT&lt;/code&gt; is not as informative as it&lt;br&gt;
could, so let's change it to put our prompt to work. As the prompt&lt;br&gt;
configuration work slightly different between &lt;code&gt;bash&lt;/code&gt; and &lt;code&gt;zsh&lt;/code&gt;, we will&lt;br&gt;
address both cases in two different sections.&lt;/p&gt;
&lt;h3&gt;
  
  
  Configuring your bash prompt
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;PS1&lt;/code&gt; environment variable can be defined by using a mix and match&lt;br&gt;
of both regular and special characters. The regular characters are just&lt;br&gt;
displayed as-is, whereas the backslash-escaped special characters are&lt;br&gt;
interpreted by bash at the time &lt;code&gt;PS1&lt;/code&gt; is displayed and replaced by the&lt;br&gt;
associated value. The most useful special characters are defined as&lt;br&gt;
follows.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Character&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;\h&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The hostname up to the first dot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;\t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The current time, in 24-hour HH:MM:SS format&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;\u&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The current user's username&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;\w&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The full current working directory (&lt;code&gt;$HOME&lt;/code&gt; rendered as &lt;code&gt;~&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;\W&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The basename of the current working directory (&lt;code&gt;$HOME&lt;/code&gt; rendered as &lt;code&gt;~&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;\n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A new line&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These special characters are evaluated every-time the prompt is displayed to make sure you always get the most up-to-date context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; The &lt;code&gt;PROMPTING&lt;/code&gt; section of the &lt;code&gt;bash&lt;/code&gt; manual contains the full list of&lt;br&gt;
backslash-escaped special characters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PS1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\u@\h \W $'&lt;/span&gt;
br@morenika ~ &lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PS1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'[\t] \u@\h \W $'&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;13:33:55] br@morenika ~ &lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PS1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'[\t \u@\h:\w]\n&amp;gt;&amp;gt;&amp;gt; '&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;13:57:55 br@morenika:~/code]
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; You can use online tools such as ezprompt&lt;sup id="fnref7"&gt;7&lt;/sup&gt; to try different&lt;br&gt;
configurations until you find something you like.&lt;/p&gt;

&lt;p&gt;Whatever &lt;code&gt;PS1&lt;/code&gt; value you settle with should be persisted and exported in&lt;br&gt;
your &lt;code&gt;.bashrc&lt;/code&gt; configuration file.&lt;/p&gt;
&lt;h3&gt;
  
  
  Configuring your zsh prompt
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;zsh&lt;/code&gt; exposes a bit more options than &lt;code&gt;bash&lt;/code&gt; when it comes to prompt&lt;br&gt;
configuration. Both &lt;code&gt;PS1&lt;/code&gt; and &lt;code&gt;PROMPT&lt;/code&gt; environment variable can be set&lt;br&gt;
to the same effect, if you find &lt;code&gt;PROMPT&lt;/code&gt; more explicit.&lt;/p&gt;

&lt;p&gt;Instead of being backslash-escaped, zsh's special characters are&lt;br&gt;
prefixed by &lt;code&gt;%&lt;/code&gt;, and are called &lt;em&gt;prompt sequences&lt;/em&gt;. The most useful are&lt;br&gt;
detailed here.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Sequence&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%m&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The hostname up to the first dot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The current time, in 24-hour HH:MM:SS format&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The current user's username&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%~&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The full current working directory (&lt;code&gt;$HOME&lt;/code&gt; rendered as &lt;code&gt;~&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%1~&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The basename of the current working directory (&lt;code&gt;$HOME&lt;/code&gt; rendered as &lt;code&gt;~&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The exit status of the last command executed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%%&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$'\n'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A new line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%B (%b)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Start (stop) bold font mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%F (%f)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Start (stop) using a given foreground color, if supported by the terminal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; You will find the full list of prompt sequences in the zsh&lt;br&gt;
documentation&lt;sup id="fnref8"&gt;8&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ export PROMPT='%n@%m %~ $ '
br@morenika ~/code $
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ export PROMPT='[%*] %n@%m %~ $ '
[23:38] br@morenika ~/code $
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ export PROMPT="[%* %n@%m %~]"$'\n'"&amp;gt;&amp;gt;&amp;gt; "
[23:41 br@morenika ~/code/izk]
&amp;gt;&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ export PROMPT="[%* %n@%m %1~]"$'\n'"%% "
[23:41 br@morenika izk]
%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;zsh&lt;/code&gt; goes even further by letting you define the content of a&lt;br&gt;
right-sided prompt, through the &lt;code&gt;RPROMPT&lt;/code&gt; environment variable, which&lt;br&gt;
uses the same syntax as &lt;code&gt;PROMPT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ export PROMPT='%~ $ '; export RPROMPT='%*'
~/code $                                              21:04:00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; To make sure your changes are persisted, &lt;code&gt;PROMPT&lt;/code&gt; and &lt;code&gt;RPROMPT&lt;/code&gt; should&lt;br&gt;
be exported in your &lt;code&gt;.zshrc&lt;/code&gt; configuration file.&lt;/p&gt;
&lt;h3&gt;
  
  
  Adding Colors
&lt;/h3&gt;

&lt;p&gt;Adding color is a good way to spice up your prompt as well as providing&lt;br&gt;
some visual context. You can use color to indicate whether you are&lt;br&gt;
running with super-user privileges, if the last command succeeded or&lt;br&gt;
failed, or simply colorized each individual part of your prompt&lt;br&gt;
(username, hostname, etc) in a different way to make it even simpler to&lt;br&gt;
parse.&lt;/p&gt;
&lt;h4&gt;
  
  
  Adding color to your bash prompt
&lt;/h4&gt;

&lt;p&gt;Bash allows you to style elements of your prompt by using 3-bit ANSI&lt;sup id="fnref9"&gt;9&lt;/sup&gt;&lt;br&gt;
codes defining a zone associated with a potential effect, foreground&lt;br&gt;
color and background color.&lt;/p&gt;

&lt;p&gt;Each effect, background or foreground color has an associated code,&lt;br&gt;
described in the following tables. The combination of these parameters&lt;br&gt;
is called &lt;span&gt;Select Graphic Rendition&lt;/span&gt;,&lt;br&gt;
which is defined as a semicolon (;) separated list of codes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;th&gt;ANSI Code&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Normal&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bold&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Faint&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Italic&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Underline&lt;/td&gt;
&lt;td&gt;&lt;code&gt;4&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strike through&lt;/td&gt;
&lt;td&gt;&lt;code&gt;9&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Background Color&lt;/th&gt;
&lt;th&gt;ANSI Code&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Red&lt;/td&gt;
&lt;td&gt;&lt;code&gt;41&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Green&lt;/td&gt;
&lt;td&gt;&lt;code&gt;42&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Brown&lt;/td&gt;
&lt;td&gt;&lt;code&gt;43&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blue&lt;/td&gt;
&lt;td&gt;&lt;code&gt;44&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Purple&lt;/td&gt;
&lt;td&gt;&lt;code&gt;45&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cyan&lt;/td&gt;
&lt;td&gt;&lt;code&gt;46&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;White&lt;/td&gt;
&lt;td&gt;&lt;code&gt;47&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright black&lt;/td&gt;
&lt;td&gt;&lt;code&gt;100&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright red&lt;/td&gt;
&lt;td&gt;&lt;code&gt;101&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright green&lt;/td&gt;
&lt;td&gt;&lt;code&gt;102&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright brown&lt;/td&gt;
&lt;td&gt;&lt;code&gt;103&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright blue&lt;/td&gt;
&lt;td&gt;&lt;code&gt;104&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright purple&lt;/td&gt;
&lt;td&gt;&lt;code&gt;105&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright cyan&lt;/td&gt;
&lt;td&gt;&lt;code&gt;106&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright white&lt;/td&gt;
&lt;td&gt;&lt;code&gt;107&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Foreground Color&lt;/th&gt;
&lt;th&gt;ANSI Code&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Black&lt;/td&gt;
&lt;td&gt;&lt;code&gt;30&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Red&lt;/td&gt;
&lt;td&gt;&lt;code&gt;31&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Green&lt;/td&gt;
&lt;td&gt;&lt;code&gt;32&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Brown&lt;/td&gt;
&lt;td&gt;&lt;code&gt;33&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blue&lt;/td&gt;
&lt;td&gt;&lt;code&gt;34&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Purple&lt;/td&gt;
&lt;td&gt;&lt;code&gt;35&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cyan&lt;/td&gt;
&lt;td&gt;&lt;code&gt;36&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;White&lt;/td&gt;
&lt;td&gt;&lt;code&gt;37&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright black&lt;/td&gt;
&lt;td&gt;&lt;code&gt;90&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright red&lt;/td&gt;
&lt;td&gt;&lt;code&gt;91&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright green&lt;/td&gt;
&lt;td&gt;&lt;code&gt;92&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright brown&lt;/td&gt;
&lt;td&gt;&lt;code&gt;93&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright blue&lt;/td&gt;
&lt;td&gt;&lt;code&gt;94&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright purple&lt;/td&gt;
&lt;td&gt;&lt;code&gt;95&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright cyan&lt;/td&gt;
&lt;td&gt;&lt;code&gt;96&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright white&lt;/td&gt;
&lt;td&gt;&lt;code&gt;97&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Examples of SGRs&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  blue text: &lt;code&gt;34&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  bold green text: &lt;code&gt;1;32&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  purple text on a white background: &lt;code&gt;35;47&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  bold red text on a bright cyan background: &lt;code&gt;1;31;106&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  bold and striked-through brown text on a green background
&lt;code&gt;1;9;33;42&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To define colorized zones in your bash prompt, use the following&lt;br&gt;
(granted, ugly) syntax:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\e[&amp;lt;SGR&amp;gt;mTEXT\e[m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PS1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'[\t] \u@\h \W \e[32m$\e[m '&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fgreen-prompt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fgreen-prompt.png" alt="The  raw `$` endraw  sign is now displayed in green"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;The &lt;code&gt;$&lt;/code&gt; sign is now displayed in green&lt;/span&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PS1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\e[31m\u\e[m@\e[32m\h\e[m \e[36m\W\e[m $ '&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fbash-colors-prompt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fbash-colors-prompt.png" alt="The username is in red, the hostname in green and the path is in cyan. "&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;The username is in red, the hostname in green and the path is in cyan. &lt;/span&gt;&lt;/p&gt;
&lt;h5&gt;
  
  
  Color palettes
&lt;/h5&gt;

&lt;p&gt;Notice how an ANSI code only maps to a color name? That's because it is&lt;br&gt;
up to your &lt;em&gt;terminal&lt;/em&gt; to interpret and render that color name into an&lt;br&gt;
actual color, meaning that the same prompt configuration could be&lt;br&gt;
rendered differently on two different terminals.&lt;/p&gt;

&lt;p&gt;Mapping ANSI color names to actual &lt;span&gt;
key="rgb"&amp;gt;RGB&lt;/span&gt; colors is done through what is called &lt;em&gt;color&lt;br&gt;
palettes&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Following are two different color schemes, as well as the associated&lt;br&gt;
rendered prompt, both using the same &lt;code&gt;PS1&lt;/code&gt; value, used in the previous&lt;br&gt;
example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fcolor-scheme-solarized-dark-ansi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fcolor-scheme-solarized-dark-ansi.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fcolor-scheme-solarized-dark.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fcolor-scheme-solarized-dark.png" alt="The popular Solarized Dark color scheme"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;The popular Solarized Dark color scheme&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fcolor-scheme-pastel-ansi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fcolor-scheme-pastel-ansi.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fcolor-scheme-pastel-dark-shell.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fcolor-scheme-pastel-dark-shell.png" alt="The Pastel (Dark Background) color scheme"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;The Pastel (Dark Background) color scheme&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;As you can see, these both look quite different from the prompt&lt;br&gt;
displayed in &lt;span&gt;the&lt;br&gt;
previous screenshot&lt;/span&gt;, even though the underlying prompt&lt;br&gt;
configuration is exactly the same. This means that, even if using 16&lt;br&gt;
colors can feel limiting, you actually can map these colors to any color&lt;br&gt;
you like. The ANSI color system just prevents you from having more than&lt;br&gt;
16 &lt;em&gt;different&lt;/em&gt; colors in your prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; I recommend you to have a look at the&lt;br&gt;
&lt;code&gt;mbadolato/iTerm2-Color-Schemes&lt;/code&gt;&lt;sup id="fnref10"&gt;10&lt;/sup&gt; project, showcasing popular color&lt;br&gt;
palettes and providing you with the configuration files allowing you to&lt;br&gt;
used them in many terminal applications (and not just iTerm2 contrary to&lt;br&gt;
what its name suggests).&lt;/p&gt;
&lt;h5&gt;
  
  
  Up to 256 colors
&lt;/h5&gt;

&lt;p&gt;As computers eventually started to have 256 colors graphics card, a 8&lt;br&gt;
bit ANSI code scheme was introduced, allowing the user to render 256&lt;br&gt;
colors in their terminal, instead of 16.&lt;/p&gt;

&lt;p&gt;The 8-bit ANSI code syntax is &lt;code&gt;\e[38;5;n&lt;/code&gt; where the colors associated&lt;br&gt;
with each value of &lt;code&gt;n&lt;/code&gt; between 0 and 255 are represented in the&lt;br&gt;
following table&lt;sup id="fnref11"&gt;11&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2F256col-table.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2F256col-table.png" alt="The 8-bit ANSI code allows you to render more than the initial 16 available colors"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;The 8-bit ANSI code allows you to render more than the initial 16 available colors&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Using 256-bit ANSI codes&lt;/span&gt;
&lt;span class="nv"&gt;$ TIME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"[&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[38;5;33m&lt;/span&gt;&lt;span class="se"&gt;\t\e&lt;/span&gt;&lt;span class="s2"&gt;[m]"&lt;/span&gt;  &lt;span class="c"&gt;# blue&lt;/span&gt;
&lt;span class="nv"&gt;$ USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[38;5;200m&lt;/span&gt;&lt;span class="se"&gt;\u\e&lt;/span&gt;&lt;span class="s2"&gt;[m"&lt;/span&gt;  &lt;span class="c"&gt;# pink&lt;/span&gt;
&lt;span class="nv"&gt;$ HOSTNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[38;5;139m&lt;/span&gt;&lt;span class="se"&gt;\h\e&lt;/span&gt;&lt;span class="s2"&gt;[m"&lt;/span&gt;  &lt;span class="c"&gt;# purple&lt;/span&gt;
&lt;span class="nv"&gt;$ WORKDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\W&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;  &lt;span class="c"&gt;# no color&lt;/span&gt;
&lt;span class="nv"&gt;$ DOLLAR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[38;5;41m&lt;/span&gt;&lt;span class="nv"&gt;$\&lt;/span&gt;&lt;span class="s2"&gt;e[m"&lt;/span&gt;  &lt;span class="c"&gt;# green&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PS1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TIME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USERNAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;@&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOSTNAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PTH&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DOLLAR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; "&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2F256col-prompt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2F256col-prompt.png" alt="These ANSI codes sure are awful to read but they make for pretty colors "&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;These ANSI codes sure are awful to read but they make for pretty colors &lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; Not all terminals support 256 colors, but most of the modern ones&lt;br&gt;
should. To this day, GNOME Terminal, Konsole, Terminator, XFCE4&lt;br&gt;
Terminal, iTerm2, Terminal (macOS) and tmux all support 256 colors.&lt;/p&gt;

&lt;p&gt;Contrary to the 3-bit ANSI codes, the 8-bit codes are insensitive to&lt;br&gt;
color schemes changes, as shown in the following examples, both re-using&lt;br&gt;
the same &lt;code&gt;PS1&lt;/code&gt; configuration than in the &lt;span&gt;
key="fig:256col-prompt"&amp;gt;previous screenshot&lt;/span&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fcolor-scheme-solarized-dark-256.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fcolor-scheme-solarized-dark-256.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fcolor-scheme-pastel-dark-256.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fcolor-scheme-pastel-dark-256.png" alt="The colors remain unchanged"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;The colors remain unchanged&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Adding color to your zsh prompt
&lt;/h4&gt;

&lt;p&gt;Everything we've explained in the previous section is still valid for&lt;br&gt;
&lt;code&gt;zsh&lt;/code&gt;: you can use 3 or 8 bit ANSI color codes just fine. However, &lt;code&gt;zsh&lt;/code&gt;&lt;br&gt;
also provides you with a much easier and readable color system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  each color can be represented as either &lt;code&gt;black&lt;/code&gt;, &lt;code&gt;red&lt;/code&gt;, &lt;code&gt;green&lt;/code&gt;,
&lt;code&gt;yellow&lt;/code&gt;, &lt;code&gt;blue&lt;/code&gt;, &lt;code&gt;magenta&lt;/code&gt;, &lt;code&gt;cyan&lt;/code&gt; or &lt;code&gt;white&lt;/code&gt;, or a number between
0 and 255&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;%F{color}Text%f&lt;/code&gt;: changes the &lt;code&gt;Text&lt;/code&gt; foreground color to &lt;code&gt;color&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;%K{color}Text%k&lt;/code&gt;: changes the &lt;code&gt;Text&lt;/code&gt; background color to &lt;code&gt;color&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;%BText%b&lt;/code&gt;: displays &lt;code&gt;Text&lt;/code&gt; in boldface&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;%UText%u&lt;/code&gt;: underlines &lt;code&gt;Text&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fzsh-colors-prompt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fzsh-colors-prompt.png" alt="The current working directory in blue and the dollar sign in bold pink"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;The current working directory in blue and the dollar sign in bold pink&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Displaying dynamic data in the prompt
&lt;/h3&gt;

&lt;p&gt;We can make our prompt display dynamic context to make it even more&lt;br&gt;
informative. To do this, we can execute a function as part of our &lt;code&gt;PS1&lt;/code&gt;&lt;br&gt;
environment variable. The shell will call that function every time it&lt;br&gt;
renders the prompt.&lt;/p&gt;

&lt;p&gt;The idea is to be able to have as much information as possible in your&lt;br&gt;
prompt at the ready, but &lt;em&gt;only when necessary&lt;/em&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Displaying dynamic data in bash
&lt;/h4&gt;

&lt;p&gt;Let's say that we want to colorize the &lt;code&gt;$&lt;/code&gt; of our prompt in green if the&lt;br&gt;
last command was successful, and in red if it failed. We can wrap that&lt;br&gt;
logic into the following &lt;code&gt;colorized_prompt&lt;/code&gt; bash function, and have it&lt;br&gt;
called every time &lt;code&gt;PS1&lt;/code&gt; is rendered by including &lt;code&gt;$(colorized_prompt)&lt;/code&gt;&lt;br&gt;
in the environment variable.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;$(colorized_prompt)&lt;/code&gt; syntax means "call the &lt;code&gt;colorize_prompt&lt;/code&gt; function", and will be expanded into the output of the function (what it prints), which will contain ASCII color codes colorizing the prompt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;colorized_prompt &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[32m&lt;/span&gt;&lt;span class="nv"&gt;$\&lt;/span&gt;&lt;span class="s2"&gt;e[m"&lt;/span&gt;
    &lt;span class="k"&gt;else
        &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;[31m&lt;/span&gt;&lt;span class="nv"&gt;$\&lt;/span&gt;&lt;span class="s2"&gt;e[m"&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PS1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'[\t] \W $(colorized_prompt) '&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; &lt;code&gt;$?&lt;/code&gt; is a special bash parameter that expands to the &lt;em&gt;exit status&lt;/em&gt; of the previously executed command. The norm is to have an exit status of 0 if the command executed successfully, and any other exit status indicates an error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pwd
/home/br
$ echo $?
0
$ cmdnotfound
bash: cmdnotfound: command not found
echo $?
127
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The syntax &lt;code&gt;if [[ $? ]]; then&lt;/code&gt; thus translates to “if the last command&lt;br&gt;
executed successfully, then…”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fred-green-prompt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fred-green-prompt.png" alt="The prompt is green after a successful command and red after a failed one"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;The prompt is green after a successful command and red after a failed one&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Displaying dynamic data in zsh
&lt;/h4&gt;

&lt;p&gt;Dynamic data can be injected in your prompt the same way than in bash,&lt;br&gt;
by executing functions at rendering time. &lt;code&gt;zsh&lt;/code&gt; however provides you&lt;br&gt;
with &lt;em&gt;ternary conditionals&lt;/em&gt;, that is to say expressions that either&lt;br&gt;
evaluate to one value or the other depending on a condition, to reach&lt;br&gt;
the same goal. A ternary conditional has the following syntax&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;%(&amp;lt;condition&amp;gt;.&amp;lt;success value&amp;gt;.&amp;lt;failure value&amp;gt;)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the condition is true, then the expression is evaluated to the&lt;br&gt;
success value. On the other hand, if the condition is false, the&lt;br&gt;
expression will be evaluated to the failure value.&lt;/p&gt;

&lt;p&gt;You can read a ternary conditional as &lt;em&gt;if condition, then, else&lt;/em&gt;. It's&lt;br&gt;
actually a common pattern called &lt;em&gt;ternary expression&lt;/em&gt; you might&lt;br&gt;
encounter in many programming languages.&lt;/p&gt;

&lt;p&gt;Here is a list of useful built-in conditions provided by &lt;code&gt;zsh&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Condition&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;n?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;True if the previous command exited with the exit status &lt;em&gt;n&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;True if the day of the month is equal to n&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nw&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;True if the day of the week is equal to n (Sunday = 0).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;True if the shell is running with super-user privileges (as the &lt;code&gt;root&lt;/code&gt; user)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ export PROMPT='%F{%(0?.green.red)}$ %f'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fzsh-ternary-red-green.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fzsh-ternary-red-green.png" alt="Displays a dollar prompt in green if the last command was successful, or red if it failed"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;Displays a dollar prompt in green if the last command was successful, or red if it failed&lt;/span&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ export PROMPT='%* %1~ %(!.#.$) '
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fzsh-ternary-root.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fzsh-ternary-root.png" alt="Display a dollar sign if you run your regular user, and a hash if you are running in super-user mode"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;Display a dollar sign if you run your regular user, and a hash if you are running in super-user mode&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; The full list of ternary conditionals is available in the zsh&lt;br&gt;
documentation&lt;sup id="fnref12"&gt;12&lt;/sup&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Adding emoji to your prompt
&lt;/h3&gt;

&lt;p&gt;Modern terminal support non-ASCII characters, such as emoji. Like&lt;br&gt;
colors, they can be convenient to convey information in a very&lt;br&gt;
space-efficient fashion.&lt;/p&gt;

&lt;p&gt;For example, during the process of writing that book, I displayed the&lt;br&gt;
associated total word count in my prompt to keep me motivated. That word&lt;br&gt;
count would however only be displayed when I was located in the root&lt;br&gt;
directory of the project, in the spirit of only displaying context when&lt;br&gt;
necessary.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fword-count-emoji.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fword-count-emoji.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="shell-configuration-frameworks"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Shell configuration frameworks
&lt;/h2&gt;

&lt;p&gt;Up until now, we have seen how to tailor your prompt by adding colors,&lt;br&gt;
context, dynamic information computed on-the-fly. While you can&lt;br&gt;
certainly spend hours customizing up to “perfection” (trust me, I have&lt;br&gt;
been there…), you can also take another route and benefit from other&lt;br&gt;
people's work, using a shell configuration &lt;span&gt;
key="framework"&amp;gt;framework&lt;/span&gt;.&lt;/p&gt;

&lt;p&gt;These frameworks provide you with a large choice of prompt themes,&lt;br&gt;
helpers, options, additional command auto-completions, plug-ins, and are&lt;br&gt;
regularly updated by a community of developers around the world.&lt;/p&gt;

&lt;p&gt;To this day, the most famous &lt;code&gt;zsh&lt;/code&gt; configuration frameworks are Oh My&lt;br&gt;
Zsh&lt;sup id="fnref13"&gt;13&lt;/sup&gt; and Prezto.&lt;sup id="fnref14"&gt;14&lt;/sup&gt; While we can't fully attribute &lt;code&gt;zsh&lt;/code&gt;'s success&lt;br&gt;
to them (Oh My Zsh was first released around 2010, 20 years after zsh's&lt;br&gt;
first release), they certainly have helped in driving community adoption&lt;br&gt;
in the last couple of years&lt;sup id="fnref15"&gt;15&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fzsh-adoption.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fzsh-adoption.png" alt="Comparison of Google Trends associated with zsh and Oh My Zsh"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;Comparison of Google Trends associated with zsh and Oh My Zsh&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;We will introduce you to the concepts behind Oh My Zsh, but it will then&lt;br&gt;
be up to you to explore, and select a theme as well as plug-ins you like&lt;br&gt;
(or even not use them at all!). After all, it is &lt;em&gt;your&lt;/em&gt; development&lt;br&gt;
environment, and henceforth, your choice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; &lt;code&gt;bash&lt;/code&gt; has a similar framework, inspired by Oh My Zsh, called&lt;br&gt;
&lt;code&gt;bash-it&lt;/code&gt;.&lt;sup id="fnref16"&gt;16&lt;/sup&gt; We won't cover it in details but we encourage you to&lt;br&gt;
look at it if don't feel like using &lt;code&gt;zsh&lt;/code&gt; but still want to use a&lt;br&gt;
configuration framework.&lt;/p&gt;
&lt;h3&gt;
  
  
  Oh My Zsh
&lt;/h3&gt;

&lt;p&gt;Quoting the official website,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Oh My Zsh is a delightful, open source, community-driven framework for&lt;br&gt;
managing your Zsh configuration. It comes bundled with thousands of&lt;br&gt;
helpful functions, helpers, plug-ins, themes, and a few things that&lt;br&gt;
make you shout…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To install it, run the following command in a shell, which will download&lt;br&gt;
an installation script, and run it on your computer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the script has finished running, you should see a message stating&lt;br&gt;
that Oh My Zsh has been installed, and that plug-ins, themes and options&lt;br&gt;
should be enabled by changing the configuration living under &lt;code&gt;~/.zshrc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before, we do, let's inspect our environment variables, to see how Oh My&lt;br&gt;
Zsh configures itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;printenv&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;ZSH
&lt;span class="nv"&gt;ZSH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/br/.oh-my-zsh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;ZSH&lt;/code&gt; environment variable points to the Oh My Zsh installation&lt;br&gt;
directory. The framework also injected a couple of other variables&lt;br&gt;
defining specific configuration values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;ZSH
&lt;span class="nv"&gt;ZSH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/br/.oh-my-zsh
&lt;span class="nv"&gt;ZSH_ARGZERO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;zsh
&lt;span class="nv"&gt;ZSH_CACHE_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/br/.oh-my-zsh/cache
&lt;span class="nv"&gt;ZSH_COMPDUMP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/br/.zcompdump-morenika-5.7.1
&lt;span class="nv"&gt;ZSH_CUSTOM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/br/.oh-my-zsh/custom
&lt;span class="nv"&gt;ZSH_EVAL_CONTEXT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;toplevel
&lt;span class="nv"&gt;ZSH_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;zsh
&lt;span class="nv"&gt;ZSH_PATCHLEVEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;zsh-5.7.1-0-g8b89d0d
&lt;span class="nv"&gt;ZSH_SPECTRUM_TEXT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Arma virumque cano Troiae qui primus ab oris'&lt;/span&gt;
&lt;span class="nv"&gt;ZSH_SUBSHELL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="nv"&gt;ZSH_THEME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;robbyrussell
&lt;span class="nv"&gt;ZSH_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5.7.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Picking a theme
&lt;/h4&gt;

&lt;p&gt;We can see that the default theme is &lt;code&gt;robbyrussell&lt;/code&gt; (Robby Russell&lt;sup id="fnref17"&gt;17&lt;/sup&gt;&lt;br&gt;
is the creator of Oh My Zsh). The full list of available themes is&lt;br&gt;
available online&lt;sup id="fnref18"&gt;18&lt;/sup&gt;, along with screenshots.&lt;/p&gt;

&lt;p&gt;You can also get the list by running the following command, as all&lt;br&gt;
themes are defined in &lt;code&gt;$ZSH/themes&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="nv"&gt;$ZSH&lt;/span&gt;/themes | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/.zsh-theme//'&lt;/span&gt;
3den
adben
af-magic
afowler
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I suggest you scroll through the themes wiki, or simply pick a theme at&lt;br&gt;
random from the previous command output, edit your &lt;code&gt;~/.zshrc&lt;/code&gt;&lt;br&gt;
configuration file by updating the value of the &lt;code&gt;ZSH_THEME&lt;/code&gt; variable,&lt;br&gt;
and run &lt;code&gt;source ~/.zshrc&lt;/code&gt; to reload it. That will get you a whole new&lt;br&gt;
shell theme!&lt;/p&gt;

&lt;p&gt;Feel free to rinse and repeat until you find a theme that suits you. In&lt;br&gt;
the case where no built-in theme finds grace in your eyes, you can also&lt;br&gt;
explore the external theme wiki&lt;sup id="fnref19"&gt;19&lt;/sup&gt;. If you find an external theme you&lt;br&gt;
like, download its associated &lt;code&gt;.zsh-theme&lt;/code&gt; file, and place it under&lt;br&gt;
&lt;code&gt;$ZSH/themes&lt;/code&gt;, then edit &lt;code&gt;~/.zshrc&lt;/code&gt;, and update the &lt;code&gt;ZSH_THEME&lt;/code&gt;&lt;br&gt;
accordingly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; If you want to further personalize a theme using some of the techniques&lt;br&gt;
we covered in that chapter, I'd advise you clone it and maintain a&lt;br&gt;
separate version, as your tweaks might get overridden at the next theme&lt;br&gt;
update.&lt;/p&gt;

&lt;p&gt;Export the &lt;code&gt;ZSH_CUSTOM&lt;/code&gt; environment variable to &lt;code&gt;$ZSH/custom&lt;/code&gt;, then run&lt;br&gt;
the following commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$ZSH&lt;/span&gt;/custom/themes
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nv"&gt;$ZSH&lt;/span&gt;/themes/&lt;span class="nv"&gt;$ZSH_THEME&lt;/span&gt;.zsh-theme &lt;span class="nv"&gt;$ZSH&lt;/span&gt;/custom/themes/&lt;span class="nv"&gt;$ZSH_THEME&lt;/span&gt;&lt;span class="nt"&gt;-custom&lt;/span&gt;.zsh-theme
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add &lt;code&gt;ZSH_THEME=&amp;lt;old zsh theme&amp;gt;-custom&lt;/code&gt; to your &lt;code&gt;~/.zshrc&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Useful configuration options
&lt;/h4&gt;

&lt;p&gt;Oh My Zsh has a couple of options you can enable or disable by editing&lt;br&gt;
&lt;code&gt;~/.zshrc&lt;/code&gt;. I suggest you take a look at them and choose what to&lt;br&gt;
activate. Here are some personal recommendations.&lt;/p&gt;
&lt;h5&gt;
  
  
  Automatic command correction
&lt;/h5&gt;

&lt;p&gt;zsh can suggest a command correction if it detects a mistyped command.&lt;br&gt;
To enable the automatic command correction, add&lt;br&gt;
&lt;code&gt;ENABLE_AUTO_CORRECTION='true'&lt;/code&gt; to &lt;code&gt;~/.zshrc&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sl
zsh: correct 'sl' to 'ls' [nyae]? y
Android                bin   Desktop    Downloads  Firefox_wallpaper.png  Pictures
AndroidStudioProjects  code  Documents  Dropbox    Music                  Videos
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The 4 options are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;n&lt;/code&gt; (no): run the mistyped command&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;y&lt;/code&gt; (yes): run the suggested command&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;a&lt;/code&gt; (abort): stop and do nothing&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;e&lt;/code&gt; (edit): edit your command before re-running it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; zsh's auto-correction feature can sometimes be over-zealous and is not&lt;br&gt;
to everyone's liking&lt;sup id="fnref20"&gt;20&lt;/sup&gt;. If you end up repeatedly fighting it for a&lt;br&gt;
given command (e.g. &lt;code&gt;git status&lt;/code&gt; wrongly autocorrected to &lt;code&gt;git stats&lt;/code&gt;),&lt;br&gt;
you can define an alias for the command by prefixing it with&lt;br&gt;
&lt;code&gt;nocorrect&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alias git status='nocorrect git status'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Automatic Oh My Zsh updates
&lt;/h5&gt;

&lt;p&gt;To make sure you regularly get new plug-ins and bug fixes, Oh My Zsh can&lt;br&gt;
automatically and regularly update itself. To do so, set the following&lt;br&gt;
options in &lt;code&gt;~/.zshrc&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;DISABLE_UPDATE_PROMPT=true&lt;/code&gt;: update Oh My Zsh without asking for
confirmation&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;UPDATE_ZSH_DAYS=30&lt;/code&gt;: update Oh My Zsh every 30 days&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Add plug-ins
&lt;/h4&gt;

&lt;p&gt;Oh My Zsh comes with more than 250 plug-ins, each of them either&lt;br&gt;
defining aliases or improved auto-completion for a given set of&lt;br&gt;
commands. Refer to the Oh My Zsh wiki page&lt;sup id="fnref21"&gt;21&lt;/sup&gt; to see the full list of&lt;br&gt;
available plug-ins. To enable a given plug-in, add its name to the&lt;br&gt;
&lt;code&gt;plugins&lt;/code&gt; list in &lt;code&gt;~/.zshrc&lt;/code&gt;, then run &lt;code&gt;source ~/.zshrc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- plugins=(git)
&lt;/span&gt;&lt;span class="gi"&gt;+ plugins=(git python)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you regularly use a command listed in the plug-in wiki page, you&lt;br&gt;
should probably try to enable the associated plug-in! I however suggest&lt;br&gt;
enabling the following general-purpose plug-ins.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;common-aliases&lt;/code&gt;&lt;sup id="fnref22"&gt;22&lt;/sup&gt;: Collection of useful aliases, not enabled by
default since they may change some user defined aliases&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;colored-man-pages&lt;/code&gt;: colorize &lt;code&gt;man&lt;/code&gt; pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fcolored-man-pages.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fcolored-man-pages.png" alt="Colorized man pages are much easier to read!"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;Colorized man pages are much easier to read!&lt;/span&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;extract&lt;/code&gt;: define an &lt;code&gt;extract&lt;/code&gt; alias that can extract any type of
archive (.zip, .tar.gz, .bzip, etc)&lt;sup id="fnref23"&gt;23&lt;/sup&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following plug-ins are not provided by default, I find them so&lt;br&gt;
useful that I suggest you install them and give them a try.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;zsh-autosuggestions&lt;/code&gt;&lt;sup id="fnref24"&gt;24&lt;/sup&gt;: emulate the &lt;code&gt;fish&lt;/code&gt; autosuggestion by
suggesting commands as you type them, saving you from using
Ctrl - R to look into your shell history. Any
suggestion can be accepted by hitting → or ignored by
just continuing typing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fzsh-autosuggestion-before.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fzsh-autosuggestion-before.png" alt="I just typed  raw `ls` endraw  and I immediately get a completion suggestion"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;I just typed &lt;code&gt;ls&lt;/code&gt; and I immediately get a completion suggestion&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fzsh-autosuggestion-after.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fzsh-autosuggestion-after.png" alt="Suggestion accepted!"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;Suggestion accepted!&lt;/span&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;zsh-syntax-highlighting&lt;/code&gt;&lt;sup id="fnref25"&gt;25&lt;/sup&gt;: provide syntax highlighting within
the zsh command line. It also colorizes the name of the command you
type in green if it is found, and in red if not.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fzsh-syntax-highlight-prompt-cmd-green.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fzsh-syntax-highlight-prompt-cmd-green.png" alt=" raw `ls` endraw  is a valid command"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;&lt;code&gt;ls&lt;/code&gt; is a valid command&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fzsh-syntax-highlight-prompt-cmd-red.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.balthazar-rouberol.com%2Fimages%2Fconfig-shell%2Fzsh-syntax-highlight-prompt-cmd-red.png" alt=" raw `cmdnotfound` endraw  is not"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span&gt;&lt;code&gt;cmdnotfound&lt;/code&gt; is not&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Uninstalling Oh My Zsh
&lt;/h4&gt;

&lt;p&gt;If you find that Oh My Zsh isn't for you, you can uninstall it by&lt;br&gt;
running the &lt;code&gt;uninstall_oh_my_zsh&lt;/code&gt; function. Your previous configuration&lt;br&gt;
will be restored.&lt;/p&gt;

&lt;p&gt;&lt;a id="summary"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I strongly believe that learning how to configure and personalize your&lt;br&gt;
own shell is an important part of becoming a developer. I'd even go as&lt;br&gt;
far as calling it a ritual. On a personal level, it helped me overcome&lt;br&gt;
the almost mystic reputation of the terminal by making it my own.&lt;/p&gt;

&lt;p&gt;Configuring your shell might never really be fully completed. Do you&lt;br&gt;
find yourself executing a long command repeatedly? Make it an alias. If&lt;br&gt;
an alias does not cut it, or if it should take arguments, write a shell&lt;br&gt;
function instead. Are you oftentimes wondering on which branch, project&lt;br&gt;
or profile you are currently running? Add it to your prompt. If your&lt;br&gt;
prompt starts to feel a little crowded, you might be able to condense it&lt;br&gt;
by using colors and emoji.&lt;/p&gt;

&lt;p&gt;Making your own tools and customizing your shell is an investment, but&lt;br&gt;
it is also an inherent part of being a software developer, which will&lt;br&gt;
allow you to do more, faster, and will help you feel more at home in&lt;br&gt;
your shell. It's also quite a bit of fun!&lt;/p&gt;

&lt;p&gt;&lt;a id="going-further"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Going further
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;4.1&lt;/strong&gt;: Look into your terminal's preferences and try to change the&lt;br&gt;
color scheme, or remap ANSI colors to different RGB colors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.2&lt;/strong&gt;: Try different fonts, such as &lt;code&gt;Source Code Pro&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;Fira Code Pro&lt;/code&gt;, &lt;code&gt;Inconsolata&lt;/code&gt; or &lt;code&gt;Jetbrains Mono&lt;/code&gt; and pick the one you&lt;br&gt;
like most&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.3&lt;/strong&gt;: Explore your terminal preferences, and experiment with&lt;br&gt;
different settings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.4&lt;/strong&gt;: Try to change the colors of the different sections of your&lt;br&gt;
prompt&lt;/p&gt;


&lt;p&gt;
&lt;em&gt;Essential Tools and Practices for the Aspiring Software Developer&lt;/em&gt; is a self-published book project by Balthazar Rouberol and &lt;a href="https://etnbrd.com" rel="noopener noreferrer"&gt;Etienne Brodu&lt;/a&gt;, ex-roommates, friends and colleagues, aiming at empowering the up and coming generation of developers. We currently are hard at work on it!
&lt;/p&gt;

&lt;p&gt;The book will help you set up a productive development environment and get acquainted with tools and practices that, along with your programming languages of choice, will go a long way in helping you grow as a software developer.
  It will cover subjects such as mastering the terminal, configuring and getting productive in a shell, the basics of code versioning with &lt;code&gt;git&lt;/code&gt;, SQL basics, tools such as &lt;code&gt;Make&lt;/code&gt;, &lt;code&gt;jq&lt;/code&gt; and regular expressions, networking basics as well as software engineering and collaboration best practices.
&lt;/p&gt;

&lt;p&gt;
  If you are interested in the project, we invite you to join the &lt;a href="https://balthazar-rouberol.us4.list-manage.com/subscribe?u=1f6080d496af07a836270ff1d&amp;amp;id=81ebd36adb" rel="noopener noreferrer"&gt;mailing list&lt;/a&gt;!
&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://gnometerminator.blogspot.com/p/introduction.html" rel="noopener noreferrer"&gt;https://gnometerminator.blogspot.com/p/introduction.html&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;&lt;a href="https://iterm2.com/" rel="noopener noreferrer"&gt;https://iterm2.com/&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;&lt;a href="https://github.com/tonsky/FiraCode" rel="noopener noreferrer"&gt;https://github.com/tonsky/FiraCode&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;&lt;a href="https://www.jetbrains.com/lp/mono/" rel="noopener noreferrer"&gt;https://www.jetbrains.com/lp/mono/&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;&lt;a href="https://www.theverge.com/2019/6/4/18651872/apple-macos-catalina-zsh-bash-shell-replacement-features" rel="noopener noreferrer"&gt;https://www.theverge.com/2019/6/4/18651872/apple-macos-catalina-zsh-bash-shell-replacement-features&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn6"&gt;
&lt;p&gt;&lt;a href="https://fishshell.com" rel="noopener noreferrer"&gt;https://fishshell.com&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn7"&gt;
&lt;p&gt;&lt;a href="http://ezprompt.net" rel="noopener noreferrer"&gt;http://ezprompt.net&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn8"&gt;
&lt;p&gt;&lt;a href="http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html" rel="noopener noreferrer"&gt;http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn9"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/ANSI_escape_code" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/ANSI_escape_code&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn10"&gt;
&lt;p&gt;&lt;a href="https://github.com/mbadolato/iTerm2-Color-Schemes" rel="noopener noreferrer"&gt;https://github.com/mbadolato/iTerm2-Color-Schemes&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn11"&gt;
&lt;p&gt;Source: &lt;a href="https://en.wikipedia.org/wiki/ANSI_escape_code#Colors" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/ANSI_escape_code#Colors&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn12"&gt;
&lt;p&gt;&lt;a href="http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html#Conditional-Substrings-in-Prompts" rel="noopener noreferrer"&gt;http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html#Conditional-Substrings-in-Prompts&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn13"&gt;
&lt;p&gt;&lt;a href="https://ohmyz.sh" rel="noopener noreferrer"&gt;https://ohmyz.sh&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn14"&gt;
&lt;p&gt;&lt;a href="https://github.com/sorin-ionescu/prezto" rel="noopener noreferrer"&gt;https://github.com/sorin-ionescu/prezto&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn15"&gt;
&lt;p&gt;Source:&lt;br&gt;
&lt;a href="https://trends.google.com/trends/explore?date=all&amp;amp;q=oh%20my%20zsh,%2Fm%2F0nrgk" rel="noopener noreferrer"&gt;https://trends.google.com/trends/explore?date=all&amp;amp;q=oh%20my%20zsh,%2Fm%2F0nrgk&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn16"&gt;
&lt;p&gt;&lt;a href="https://github.com/Bash-it/bash-it" rel="noopener noreferrer"&gt;https://github.com/Bash-it/bash-it&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn17"&gt;
&lt;p&gt;&lt;a href="https://github.com/robbyrussell" rel="noopener noreferrer"&gt;https://github.com/robbyrussell&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn18"&gt;
&lt;p&gt;&lt;a href="https://github.com/ohmyzsh/ohmyzsh/wiki/Themes" rel="noopener noreferrer"&gt;https://github.com/ohmyzsh/ohmyzsh/wiki/Themes&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn19"&gt;
&lt;p&gt;&lt;a href="https://github.com/ohmyzsh/ohmyzsh/wiki/External-themes" rel="noopener noreferrer"&gt;https://github.com/ohmyzsh/ohmyzsh/wiki/External-themes&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn20"&gt;
&lt;p&gt;&lt;a href="https://github.com/ohmyzsh/ohmyzsh/issues/534" rel="noopener noreferrer"&gt;https://github.com/ohmyzsh/ohmyzsh/issues/534&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn21"&gt;
&lt;p&gt;&lt;a href="https://github.com/ohmyzsh/ohmyzsh/wiki/Plugins" rel="noopener noreferrer"&gt;https://github.com/ohmyzsh/ohmyzsh/wiki/Plugins&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn22"&gt;
&lt;p&gt;&lt;a href="https://github.com/ohmyzsh/ohmyzsh/wiki/Plugins#common-aliases" rel="noopener noreferrer"&gt;https://github.com/ohmyzsh/ohmyzsh/wiki/Plugins#common-aliases&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn23"&gt;
&lt;p&gt;&lt;a href="https://www.xkcd.com/1168/" rel="noopener noreferrer"&gt;https://www.xkcd.com/1168/&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn24"&gt;
&lt;p&gt;&lt;a href="https://github.com/zsh-users/zsh-autosuggestions/blob/master/INSTALL.md" rel="noopener noreferrer"&gt;https://github.com/zsh-users/zsh-autosuggestions/blob/master/INSTALL.md&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn25"&gt;
&lt;p&gt;&lt;a href="https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/INSTALL.md" rel="noopener noreferrer"&gt;https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/INSTALL.md&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>tutorial</category>
      <category>bash</category>
      <category>beginners</category>
      <category>linux</category>
    </item>
    <item>
      <title>The shell's building blocks
</title>
      <dc:creator>Balthazar Rouberol</dc:creator>
      <pubDate>Sat, 04 Apr 2020 19:46:58 +0000</pubDate>
      <link>https://dev.to/brouberol/the-shell-s-building-blocks-1il</link>
      <guid>https://dev.to/brouberol/the-shell-s-building-blocks-1il</guid>
      <description>&lt;p&gt;Originally posted on my &lt;a href="https://blog.balthazar-rouberol.com/the-shells-building-blocks"&gt;blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As we have seen in the previous chapters, the shell is a program allowing you to run other programs. It is an invaluable tool in the life of a software engineer, as it provides you with a simple text-based interface to control your computer and any program you might install or write.&lt;/p&gt;

&lt;p&gt;Something I still find striking after years of using a shell almost daily is how simple yet powerful its building blocks are.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.balthazar-rouberol.com/discovering-the-terminal"&gt;Chapter 1&lt;/a&gt; covered commands, I/O streams and pipes. This chapter will cover environment variables, aliases and functions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Environment variables
&lt;/h2&gt;

&lt;p&gt;Environment variables are key/value pairs that affect how running programs behave. Another way to say that would be that environment variables can allow you to tweak and personalize how certain programs, amongst which your shell, work. They can also define what programs will be called to perform a certain task.&lt;/p&gt;

&lt;p&gt;Here are a few examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SHELL&lt;/code&gt; defines what shell your terminal runs ('/bin/bash', &lt;code&gt;/bin/zsh&lt;/code&gt;, &lt;code&gt;/bin/fish&lt;/code&gt;, etc)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;HOME&lt;/code&gt; defines where your home directory is located&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;EDITOR&lt;/code&gt; defines what text editor program should be used to edit text within your terminal (eg &lt;code&gt;nano&lt;/code&gt;, &lt;code&gt;vim&lt;/code&gt;, &lt;code&gt;emacs&lt;/code&gt;, etc)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Displaying an environment variable's value
&lt;/h3&gt;

&lt;p&gt;To display the value of given environment variable, you can use the &lt;code&gt;echo&lt;/code&gt; command, followed by a dollar sign and the name of the variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$SHELL&lt;/span&gt;
/bin/zsh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can use the &lt;code&gt;printenv&lt;/code&gt; command to list all environment variables along with their value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;printenv
&lt;/span&gt;&lt;span class="nv"&gt;USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;br
&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/br
&lt;span class="nv"&gt;LC_TERMINAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;terminator
&lt;span class="nv"&gt;SHELL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/bin/zsh
&lt;span class="nv"&gt;EDITOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;vim
&lt;span class="nv"&gt;PWD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/br/
&lt;span class="nv"&gt;PAGER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;less
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For the sake of brevity, I've only displayed a subset of the environment variables defined on my computer. These variables tell the following story:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;my username is &lt;code&gt;br&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;all my personal data is stored in my &lt;em&gt;home directory&lt;/em&gt;, located at &lt;code&gt;/home/br&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;my default terminal is called &lt;code&gt;terminator&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;and whenever I open &lt;code&gt;terminator&lt;/code&gt;, it runs the commands via the &lt;code&gt;zsh&lt;/code&gt; shell&lt;/li&gt;
&lt;li&gt;my default text editor is &lt;code&gt;vim&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;I am currently located in my home directory&lt;/li&gt;
&lt;li&gt;my default pager program is &lt;code&gt;less&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Changing an environment variable
&lt;/h3&gt;

&lt;p&gt;What is interesting about these environment variables is that they can be changed, and with them, the behavior of other programs.&lt;/p&gt;

&lt;p&gt;For example, let's change the value of our &lt;code&gt;HOME&lt;/code&gt; environment variable, defining where our home directory is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/tmp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the first line, I redefined the value of my &lt;code&gt;HOME&lt;/code&gt; environment variable from &lt;code&gt;/home/br&lt;/code&gt; to &lt;code&gt;/tmp&lt;/code&gt;. Remember when you learned that running &lt;code&gt;cd&lt;/code&gt; without arguments would take you back to your home directory? Well, it's actually using the &lt;code&gt;HOME&lt;/code&gt; environment variable to figure out where your home directory is. Now that &lt;code&gt;HOME&lt;/code&gt; has changed, so has &lt;code&gt;cd&lt;/code&gt;'s behavior.&lt;/p&gt;

&lt;p&gt;Another example is &lt;code&gt;PAGER&lt;/code&gt;. We saw that my environment had &lt;code&gt;PAGER=less&lt;/code&gt; defined by default, which explains why you find yourself reading text within &lt;code&gt;less&lt;/code&gt; when you open a man page. &lt;code&gt;man&lt;/code&gt; fetches the actual documentation and displays it in a pager, which itself is specified by the &lt;code&gt;PAGER&lt;/code&gt; environment variable. If you were to change that variable to something else, like &lt;code&gt;more&lt;/code&gt; or &lt;code&gt;bat&lt;/code&gt; &lt;sup id="fnref1"&gt;1&lt;/sup&gt;, it would then change &lt;code&gt;man&lt;/code&gt;'s behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: There is a difference between &lt;code&gt;SHELL&lt;/code&gt; and &lt;code&gt;$SHELL&lt;/code&gt;. The first one is the name of an environment variable, and the latter represents its value. Consequently, when we executed &lt;code&gt;echo $SHELL&lt;/code&gt;, we told our shell to lookup what value was associated with the &lt;code&gt;SHELL&lt;/code&gt; environment variable, and then display it to the screen via the &lt;code&gt;echo&lt;/code&gt; command. &lt;code&gt;$&lt;/code&gt; is what we call a &lt;em&gt;dereference operator&lt;/em&gt; in that context.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining new variables
&lt;/h3&gt;

&lt;p&gt;Not only can you change an existing environment variable, but you can also define a new one. If a non-existing variable is &lt;code&gt;echo&lt;/code&gt;-ed, it will simply be replaced by an empty string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$NEW_VAR&lt;/span&gt;

&lt;span class="nv"&gt;$ NEW_VAR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;my-new-env-var
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$NEW_VAR&lt;/span&gt;
my-new-env-var
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you define an environment variable this way, it will only be visible by the shell itself, but not by any command executed by your shell (also called &lt;em&gt;subprocesses&lt;/em&gt;). To make an environment variable visible by a subprocess, you need to define it after the &lt;code&gt;export&lt;/code&gt; keyword.&lt;/p&gt;

&lt;p&gt;To illustrate that, we will create our first &lt;em&gt;shell script&lt;/em&gt;: a program executing shell commands one after the others.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt; echo_var.sh
echo &lt;/span&gt;&lt;span class="nv"&gt;$NEW_VAR&lt;/span&gt;&lt;span class="sh"&gt;
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;echo_var.sh
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$NEW_VAR&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, the &lt;code&gt;echo_var.sh&lt;/code&gt; &lt;em&gt;script&lt;/em&gt; only contains one shell command: &lt;code&gt;echo $NEW_VAR&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To execute that bash script, we can run &lt;code&gt;bash echo_var.sh&lt;/code&gt;, and all instructions within that script will be executed by &lt;code&gt;bash&lt;/code&gt;. Let's have a look at what executing that script displays on the screen with and without &lt;code&gt;export&lt;/code&gt;-ing that variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ NEW_VAR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;my-new-var
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$NEW_VAR&lt;/span&gt;
my-new-var
&lt;span class="nv"&gt;$ &lt;/span&gt;bash echo_var.sh

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NEW_VAR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;my-new-var
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$NEW_VAR&lt;/span&gt;
my-new-var
&lt;span class="nv"&gt;$ &lt;/span&gt;bash echo_var.sh
my-new-var
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, the &lt;code&gt;echo_var.sh&lt;/code&gt; subprocess can see the &lt;code&gt;NEW_VAR&lt;/code&gt; environment variable after it has been &lt;code&gt;export&lt;/code&gt;-ed by its parent shell.&lt;/p&gt;

&lt;p&gt;This can very useful if you write programs: some parameters can have a sane default value but can also be overridden by specifying an environment variable. &lt;code&gt;grep&lt;/code&gt; does this for example: reading the &lt;code&gt;grep&lt;/code&gt; &lt;code&gt;man&lt;/code&gt; page, we see:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;GREP_OPTIONS&lt;/code&gt;  May be used to specify default options that will be placed at the beginning of the argument list.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Removing environment variables
&lt;/h3&gt;

&lt;p&gt;You can remove an environment variable by using the &lt;code&gt;unset&lt;/code&gt; keyword:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;unset &lt;/span&gt;NEW_VAR
&lt;span class="nv"&gt;$ &lt;/span&gt;bash echo_var.sh

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$NEW_VAR&lt;/span&gt;

&lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  The case of &lt;code&gt;PATH&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Until that point, we've executed commands in the shell, and things happened. It was a simple world and it was nice. You might wonder &lt;em&gt;what would happen if I gave the shell a non-existent command though?&lt;/em&gt;. Well, I'm glad you asked. Ten points for Gryffindor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cmdnotfound
zsh: &lt;span class="nb"&gt;command &lt;/span&gt;not found: cmdnotfound
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;cmdnotfound&lt;/code&gt; command, like its name implies, is not found. But what makes a command be found then? What makes the shell happily comply when we type &lt;code&gt;ls&lt;/code&gt;, and makes it complain when we type &lt;code&gt;cmdnotfound&lt;/code&gt;? It turns out that this is due to an environment variable called &lt;code&gt;PATH&lt;/code&gt;,  listing all directories in which executable programs can be found.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$PATH&lt;/span&gt;
/home/br/bin:/home/br/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This means that for any command passed to the shell, it will look into these directories (separated by a colon) in search for the program I'm trying to run.&lt;/p&gt;

&lt;p&gt;For example, if I type&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;into my shell, it will look into &lt;code&gt;/home/br/bin&lt;/code&gt;,  &lt;code&gt;/home/br/.local/bin&lt;/code&gt;, &lt;code&gt;/usr/local/sbin&lt;/code&gt;,  etc, until it finds it in &lt;code&gt;/bin&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; /bin
...
&lt;span class="nb"&gt;chmod      dd         &lt;/span&gt;ed        &lt;span class="nb"&gt;ls         &lt;/span&gt;ps         sh         tcsh       zsh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If the command is not found in any of the directories listed in &lt;code&gt;PATH&lt;/code&gt;, then it is not found.&lt;/p&gt;

&lt;p&gt;This means that you can also redefine &lt;code&gt;PATH&lt;/code&gt; to force your shell to look into new directories. In fact, this is exactly what I've done to make it look into &lt;code&gt;/home/br/bin&lt;/code&gt;, where I store tools of my making.&lt;/p&gt;

&lt;p&gt;::: Warning&lt;br&gt;
You can mess with up your shell by running &lt;code&gt;unset PATH&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;unset &lt;/span&gt;PATH
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls
&lt;/span&gt;zsh: &lt;span class="nb"&gt;command &lt;/span&gt;not found: &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;However, calling a command by using its absolute or relative path still works, as &lt;code&gt;PATH&lt;/code&gt; is only used to look for commands that only have been invoked by name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;unset &lt;/span&gt;PATH
&lt;span class="nv"&gt;$ &lt;/span&gt;/bin/ls
bin    code    Documents  ..
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;:::&lt;/p&gt;

&lt;p&gt;There is a useful command you can use to know what a program is and where it is found: &lt;code&gt;which&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;which less
/usr/bin/less
&lt;span class="nv"&gt;$ &lt;/span&gt;which bash
/usr/local/bin/bash
&lt;span class="nv"&gt;$ &lt;/span&gt;which &lt;span class="nb"&gt;ls
ls&lt;/span&gt;: aliased to &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-G&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Wait. What? What's an alias?&lt;/p&gt;

&lt;h2&gt;
  
  
  Aliases
&lt;/h2&gt;

&lt;p&gt;An &lt;em&gt;alias&lt;/em&gt; allows you to define custom commands. In the previous example, running &lt;code&gt;ls&lt;/code&gt; would actually run &lt;code&gt;ls -G&lt;/code&gt;, which enables colorized output.&lt;/p&gt;

&lt;p&gt;You can define an alias by using the &lt;code&gt;alias&lt;/code&gt; keyword.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;alias ls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ls -G'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There are a couple of reasons you might want to define aliases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;redefining a command's behavior (ex: always using &lt;code&gt;ls&lt;/code&gt; with the &lt;code&gt;-G&lt;/code&gt; option)&lt;/li&gt;
&lt;li&gt;shortening a command's name to make it quicker to type (ex: &lt;code&gt;alias ..='cd ..'&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;creating new commands altogether (ex: &lt;code&gt;alias filesize='ls --size --human-readable -1'&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To see the underlying command that will be executed by an alias, you can type &lt;code&gt;alias &amp;lt;name&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;filesize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ls --size --human-readable -1'&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;filesize
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;filesize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ls --size --human-readable -1'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Aliases are very simple yet powerful. They allow you to customize your shell to your liking, create new commands without having to remember a lot of options, and decrease the time you spend typing, all of which should make you feel more productive.&lt;/p&gt;

&lt;p&gt;:::Note&lt;br&gt;
Aliases can be "nested". If you define &lt;code&gt;ls&lt;/code&gt; as an alias of &lt;code&gt;ls -G&lt;/code&gt; and &lt;code&gt;filesize&lt;/code&gt; as an alias of &lt;code&gt;ls --size --human-readable -1&lt;/code&gt;, your shell will unwrap both aliases and execute &lt;code&gt;ls -G --size --human-readable -1&lt;/code&gt; when you type &lt;code&gt;filesize&lt;/code&gt;.&lt;br&gt;
:::&lt;/p&gt;

&lt;p&gt;When we're executing &lt;code&gt;filesize bin&lt;/code&gt;, the shell will see that &lt;code&gt;filesize&lt;/code&gt; is an alias for &lt;code&gt;ls --size --human-readable -1&lt;/code&gt; and will actually execute the command &lt;code&gt;ls --size --human-readable -1 bin&lt;/code&gt; behind the scenes. This simply is done by replacing the alias by its definition in the command itself. Aliases can however fall short if we want to do something a more complex than this.&lt;/p&gt;

&lt;p&gt;For example, one of my favorite productivity tools is &lt;code&gt;mkcd&lt;/code&gt;, which creates a directory and steps into it right after. It saves you from typing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;new-dir
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;new-dir
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;where you can just type&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mkcd new-dir
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;An alias can't really help here, because we are talking about aliasing two commands with a single alias, which does not work. Enter &lt;em&gt;functions&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Functions
&lt;/h2&gt;

&lt;p&gt;According to the &lt;code&gt;bash&lt;/code&gt; &lt;code&gt;man&lt;/code&gt; page:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A shell function is an object that is called like a simple command and executes a compound command with a new set of positional parameters.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's see what that looks like in practice. A function is declared this way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;name &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;# ...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If your function is expecting arguments, these can be accessed by using &lt;code&gt;$n&lt;/code&gt; where &lt;code&gt;n&lt;/code&gt; is a number. For example, &lt;code&gt;$1&lt;/code&gt; is the first function argument, &lt;code&gt;$2&lt;/code&gt; its second argument, etc. With that in mind, we can now declare our &lt;code&gt;mkcd&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;mkcd &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt;
    &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's now see &lt;code&gt;mkcd&lt;/code&gt; in action!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="k"&gt;function &lt;/span&gt;mkcd &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
    &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$target&lt;/span&gt;
    &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$target&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br
&lt;span class="nv"&gt;$ &lt;/span&gt;mkcd &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br/test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can use the &lt;code&gt;typeset -f&lt;/code&gt; command to see how a function was defined (or &lt;code&gt;which &amp;lt;function-name&amp;gt;&lt;/code&gt;, although that only works in &lt;code&gt;zsh&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;typeset&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; mkcd
mkcd &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt;
    &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Real life examples
&lt;/h2&gt;

&lt;p&gt;These are some of the environment variables, aliases and functions I have defined for myself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shorter navigation aliases
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; ..&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'cd ..'&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt; ...&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'cd ../..'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Colorize commands output
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias ls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ls --color=auto'&lt;/span&gt;
&lt;span class="nb"&gt;alias grep&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'grep --color=auto'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;ip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ip --color'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Alias commands I never remember
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# https://xkcd.com/1168/&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;untar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'tar -zxvf'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Have &lt;code&gt;$HOME/bin&lt;/code&gt; be part of &lt;code&gt;PATH&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;:&lt;span class="nv"&gt;$HOME&lt;/span&gt;/bin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By extending my &lt;code&gt;PATH&lt;/code&gt; this way, I can then put every single tool I create into &lt;code&gt;$HOME/bin&lt;/code&gt; and have it be usable right-away.&lt;/p&gt;

&lt;h3&gt;
  
  
  A backup function
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;bak &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt;.bak
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This function can be used to backup a file or directory. I regularly use this when I'm about to edit a critical file and I want to make sure I can revert my changes if needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Password generation function
&lt;/h3&gt;

&lt;p&gt;This function generate a password composed of alphanumeric characters, of default length 32.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="k"&gt;function &lt;/span&gt;genpass &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;passlen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;32&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;# Note: LC_ALL=C is needed for macos compatibility&lt;/span&gt;
    &lt;span class="nv"&gt;LC_ALL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;C &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-cd&lt;/span&gt; &lt;span class="s1"&gt;'[:alnum:]'&lt;/span&gt; &amp;lt; /dev/urandom | &lt;span class="nb"&gt;fold&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="nv"&gt;$passlen&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n1&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;genpass
GQROc0tnABqfYH0qpMMwSPYFgcY7OANB
&lt;span class="nv"&gt;$ &lt;/span&gt;genpass 50
WkeQ14E8FIQZN7XlN7yPkYK4yhMOvpAuNzZivKwODNkskh0uq0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  The weather in your terminal
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;weather &lt;span class="o"&gt;{&lt;/span&gt;
    curl &lt;span class="s2"&gt;"wttr.in/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;lyon&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;?m"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This function uses &lt;code&gt;curl&lt;/code&gt; to send an HTTP request to the &lt;code&gt;http://wttr.in&lt;/code&gt; website, that displays weather forecasts in a terminal-friendly way. So I can just type &lt;code&gt;weather mycity&lt;/code&gt; and &lt;em&gt;voila&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ weather lyon
Weather report: lyon

     \   /     Sunny
      .-.      17 °C
   ― (   ) ―   ↖ 6 km/h
      `-’      10 km
     /   \     0.0 mm
                                                       ┌─────────────┐
┌──────────────────────────────┬───────────────────────┤  Sat 04 Apr ├───────────────────────┬──────────────────────────────┐
│            Morning           │             Noon      └──────┬──────┘     Evening           │             Night            │
├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤
│    \  /       Partly cloudy  │    \  /       Partly cloudy  │    \  /       Partly cloudy  │    \  /       Partly cloudy  │
│  _ /"".-.     7..8 °C        │  _ /"".-.     13 °C          │  _ /"".-.     13 °C          │  _ /"".-.     10..11 °C      │
│    \_(   ).   ← 5-6 km/h     │    \_(   ).   ↙ 5 km/h       │    \_(   ).   ← 5-10 km/h    │    \_(   ).   ↖ 8-17 km/h    │
│    /(___(__)  10 km          │    /(___(__)  10 km          │    /(___(__)  10 km          │    /(___(__)  10 km          │
│               0.0 mm | 0%    │               0.0 mm | 0%    │               0.0 mm | 0%    │               0.0 mm | 0%    │
└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘
                                                       ┌─────────────┐
┌──────────────────────────────┬───────────────────────┤  Sun 05 Apr ├───────────────────────┬──────────────────────────────┐
│            Morning           │             Noon      └──────┬──────┘     Evening           │             Night            │
├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤
│     \   /     Sunny          │     \   /     Sunny          │     \   /     Sunny          │    \  /       Partly cloudy  │
│      .-.      10..12 °C      │      .-.      16 °C          │      .-.      14..15 °C      │  _ /"".-.     10..12 °C      │
│   ― (   ) ―   ↖ 14-18 km/h   │   ― (   ) ―   ↑ 23-27 km/h   │   ― (   ) ―   ↑ 15-25 km/h   │    \_(   ).   ↑ 13-26 km/h   │
│      `-’      10 km          │      `-’      10 km          │      `-’      10 km          │    /(___(__)  10 km          │
│     /   \     0.0 mm | 0%    │     /   \     0.0 mm | 0%    │     /   \     0.0 mm | 0%    │               0.0 mm | 0%    │
└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘
                                                       ┌─────────────┐
┌──────────────────────────────┬───────────────────────┤  Mon 06 Apr ├───────────────────────┬──────────────────────────────┐
│            Morning           │             Noon      └──────┬──────┘     Evening           │             Night            │
├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤
│     \   /     Sunny          │     \   /     Sunny          │     \   /     Sunny          │     \   /     Clear          │
│      .-.      12..13 °C      │      .-.      16 °C          │      .-.      14..15 °C      │      .-.      11 °C          │
│   ― (   ) ―   ↖ 18-22 km/h   │   ― (   ) ―   ↑ 22-28 km/h   │   ― (   ) ―   ↑ 14-24 km/h   │   ― (   ) ―   ↑ 8-16 km/h    │
│      `-’      10 km          │      `-’      10 km          │      `-’      10 km          │      `-’      10 km          │
│     /   \     0.0 mm | 0%    │     /   \     0.0 mm | 0%    │     /   \     0.0 mm | 0%    │     /   \     0.0 mm | 0%    │
└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘
Location: Lyon, Métropole de Lyon, Circonscription départementale du Rhône, Auvergne-Rhône-Alpes, France [45.7578137,4.8320114]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Environment variables, aliases and functions are simple yet powerful to change the shell's behavior into something that feels more intuitive. You feel like &lt;code&gt;nano&lt;/code&gt; is not shiny enough and prefer using &lt;code&gt;vim&lt;/code&gt; instead? Sure. Define &lt;code&gt;EDITOR=vim&lt;/code&gt;. Any command interacting with an editor would then use &lt;code&gt;vim&lt;/code&gt; instead of &lt;code&gt;nano&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Aliases are a great way to reduce mental friction in the shell by hiding away complex commands, or just reducing the amount of typing you have to do. When aliases start being not powerful enough because you want to execute multiple commands, you can then have a look at functions instead.&lt;/p&gt;

&lt;p&gt;Everything we have seen so far however had an ephemeral effect, as changes you made would disappear when you close your shell session. In the next chapter, we will go dive into how to persistently configure your shell to improve your day-to-day experience and productivity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Going further
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;3.1&lt;/strong&gt;: Write a &lt;code&gt;cat&lt;/code&gt; alias that displays &lt;code&gt;meow&lt;/code&gt; on screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.2&lt;/strong&gt;: Write a &lt;code&gt;restorebak&lt;/code&gt; function that takes a filename as only argument and renames &lt;code&gt;$1.bak&lt;/code&gt; into &lt;code&gt;$1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.3&lt;/strong&gt;: Unset the &lt;code&gt;PATH&lt;/code&gt; environment variable and then export it back so that you can use &lt;code&gt;ls&lt;/code&gt; again.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://github.com/sharkdp/bat"&gt;https://github.com/sharkdp/bat&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>bash</category>
      <category>linux</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Text processing in the shell</title>
      <dc:creator>Balthazar Rouberol</dc:creator>
      <pubDate>Sat, 28 Mar 2020 13:55:47 +0000</pubDate>
      <link>https://dev.to/brouberol/text-processing-in-the-shell-52jn</link>
      <guid>https://dev.to/brouberol/text-processing-in-the-shell-52jn</guid>
      <description>&lt;p&gt;Originally posted on my &lt;a href="https://blog.balthazar-rouberol.com/text-processing-in-the-shell"&gt;blog&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cat&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;head&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tail&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grep&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cut&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;paste&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sort&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uniq&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;awk&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tr&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fold&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sed&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Going further: &lt;code&gt;for&lt;/code&gt; loops and &lt;code&gt;xargs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;li&gt;Exercices&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Text processing in the shell
&lt;/h1&gt;

&lt;p&gt;One of the things that makes the shell an invaluable tool is the amount of available text processing commands, and the ability to easily pipe them into each other to build complex text processing workflows. These commands can make it trivial to perform text and data analysis, convert data between different formats, filter lines, etc.&lt;/p&gt;

&lt;p&gt;When working with text data, the philosophy is to break any complex problem you have into a set of smaller ones, and to solve each of them with a specialized tool.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make each program do one thing well.&lt;sup id="fnref:1"&gt;1&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The examples in that chapter might seem a little contrived at first, but this is also by design. Each of these tools were designed to solve one small problem. They however become extremely powerful when combined.&lt;/p&gt;

&lt;p&gt;We will go over some of the most common and useful text processing commands the shell has to offer, and will demonstrate real-life workflows piping them together. I suggest you take a look at the &lt;code&gt;man&lt;/code&gt; of these commands to see the full breadth of options at your disposal.&lt;/p&gt;

&lt;p&gt;The example CSV (comma-separated values) file is available &lt;a href="https://raw.githubusercontent.com/DataDog/integrations-core/master/mysql/metadata.csv"&gt;online&lt;/a&gt;. Feel free to download it yourself to test these commands.&lt;/p&gt;

&lt;p&gt;&lt;a id="cat"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;cat&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;As seen in the previous chapter, &lt;code&gt;cat&lt;/code&gt; is used to concatenate a list of one or more files and displays their content on screen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;Documents/readme
Thanks again &lt;span class="k"&gt;for &lt;/span&gt;reading this book!
I hope you&lt;span class="s1"&gt;'re following so far!
$ cat Documents/computers
Computers are not intelligent
They'&lt;/span&gt;re just fast at making dumb things.
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;Documents/readme Documents/computers
Thanks again &lt;span class="k"&gt;for &lt;/span&gt;reading this book!
I hope you are following so far!
Computers are not intelligent
They&lt;span class="s1"&gt;'re just fast at making dumb things.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a id="head"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;head&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;head&lt;/code&gt; prints the first n lines in a file. It can be very useful to peek into a file of unknown structure and format without burying your shell under a wall of text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 2 metadata.csv
metric_name,metric_type,interval,unit_name,per_unit_name,description,orientation,integration,short_name
mysql.galera.wsrep_cluster_size,gauge,,node,,The current number of nodes &lt;span class="k"&gt;in &lt;/span&gt;the Galera cluster.,0,mysql,galera cluster size
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;-n&lt;/code&gt; is unspecified, &lt;code&gt;head&lt;/code&gt; will print the first 10 lines in its argument file or input stream.&lt;/p&gt;

&lt;p&gt;&lt;a id="tail"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;tail&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;tail&lt;/code&gt; is &lt;code&gt;head&lt;/code&gt;’s counterpart. It prints the last n lines in a file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1 metadata.csvmysql.performance.queries,gauge,,query,second,The rate of queries.,0,mysql,queries
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you want to print all lines in a file located after the nth line(included), you can use the &lt;code&gt;-n +n&lt;/code&gt; argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; +42 metadata.csv
mysql.replication.slaves_connected,gauge,,,,Number of slaves connected to a replication master.,0,mysql,slaves connected
mysql.performance.queries,gauge,,query,second,The rate of queries.,0,mysql,queries
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Our file has 43 lines, so &lt;code&gt;tail -n +42&lt;/code&gt; only prints the 42nd and 43rd line in our file.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;-n&lt;/code&gt; is unspecified, &lt;code&gt;tail&lt;/code&gt; will print the last 10 lines in its argument file or input stream.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tail -f&lt;/code&gt; or &lt;code&gt;tail --follow&lt;/code&gt; displays the last lines in a file and displays each new line as the file is being written to. It is very useful to see real time activity that is written to a log file, for example a web server log file, etc.&lt;/p&gt;

&lt;p&gt;&lt;a id="wc"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;wc&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;wc&lt;/code&gt; (for &lt;em&gt;word count&lt;/em&gt;) prints either the number of characters (when using &lt;code&gt;-c&lt;/code&gt;), words (when using &lt;code&gt;-w&lt;/code&gt;) or lines (when using &lt;code&gt;-l&lt;/code&gt;) in its argument files or input stream.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; metadata.csv
43 metadata.csv
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; metadata.csv
405 metadata.csv
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; metadata.csv
5094 metadata.csv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By default, &lt;code&gt;wc&lt;/code&gt; prints all of the above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;wc &lt;/span&gt;metadata.csv
43 405 5094 metadata.csv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Only the count will be printed out if the text data is piped in or redirected into &lt;code&gt;stdin&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;metadata.csv | &lt;span class="nb"&gt;wc
&lt;/span&gt;43 405 5094
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;metadata.csv | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
43
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; &amp;lt; metadata.csv
405
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a id="grep"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;grep&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;grep&lt;/code&gt; is the Swiss Army knife of line filtering. It allows you to filter lines matching a given pattern.&lt;/p&gt;

&lt;p&gt;For example, we can use &lt;code&gt;grep&lt;/code&gt; to find all occurrences of the word &lt;em&gt;mutex&lt;/em&gt; in our &lt;code&gt;metadata.csv&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep &lt;/span&gt;mutex metadata.csv
mysql.innodb.mutex_os_waits,gauge,,event,second,The rate of mutex OS waits.,0,mysql,mutex os waits
mysql.innodb.mutex_spin_rounds,gauge,,event,second,The rate of mutex spin rounds.,0,mysql,mutex spin rounds
mysql.innodb.mutex_spin_waits,gauge,,event,second,The rate of mutex spin waits.,0,mysql,mutex spin waits
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;grep&lt;/code&gt; can either filter files passed as arguments, or a stream of text passed to its &lt;code&gt;stdin&lt;/code&gt;. We can thus chain multiple &lt;code&gt;grep&lt;/code&gt; commands to further filter our text. In the next example, we filter lines in our&lt;code&gt;metadata.csv&lt;/code&gt; file that contain both the &lt;em&gt;mutex&lt;/em&gt; and &lt;em&gt;OS&lt;/em&gt; words.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep &lt;/span&gt;mutex metadata.csv | &lt;span class="nb"&gt;grep &lt;/span&gt;OS
mysql.innodb.mutex_os_waits,gauge,,event,second,The rate of mutex OS waits.,0,mysql,mutex os waits
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s go over some of the options you can pass to grep and their associated behavior.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grep -v&lt;/code&gt; performs an invert matching: it filters the lines that do_not_ match the argument pattern.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; gauge metadata.csv
metric_name,metric_type,interval,unit_name,per_unit_name,description,orientation,integration,short_name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;grep -i&lt;/code&gt; performs a case-insensitive matching. In the next example&lt;code&gt;grep -i os&lt;/code&gt; matches both &lt;em&gt;OS&lt;/em&gt; and &lt;em&gt;os&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; os metadata.csv
mysql.innodb.mutex_os_waits,gauge,,event,second,The rate of mutex OS waits.,0,mysql,mutex os waitsmysql.innodb.os_log_fsyncs,gauge,,write,second,The rate of fsync writes to the log file.,0,mysql,log fsyncs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;grep -l&lt;/code&gt; only lists files containing a match.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; mysql metadata.csv
metadata.csv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;grep -c&lt;/code&gt; counts the number of times a pattern was found.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="k"&gt;select &lt;/span&gt;metadata.csv3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;grep -r&lt;/code&gt; recursively searches files in the current working directory and all subdirectories below it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; are ~/Documents/home/br/Documents/computers:Computers are not intelligent/home/br/Documents/readme:I hope you are following so far!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;grep -w&lt;/code&gt; only matches whole words.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep &lt;/span&gt;follow ~/Documents/readmeI hope you are following so far!&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; follow ~/Documents/readme&lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a id="cut"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;cut&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;cut&lt;/code&gt; cuts out a portion of a file (or, as always, its input stream).&lt;code&gt;cut&lt;/code&gt; works by defining a field delimited (what separates two columns)with the &lt;code&gt;-d&lt;/code&gt; option, and what column(s) should be extracted, with the&lt;code&gt;-f&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;For example, the following command extracts the first column of the last 5 lines our CSV file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 5 metadata.csv | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; , &lt;span class="nt"&gt;-f&lt;/span&gt; 1
mysql.performance.user_time
mysql.replication.seconds_behind_master
mysql.replication.slave_runnin
mysql.replication.slaves_connected
mysql.performance.queries
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As we are dealing with a CSV file, we can extract each column by cutting over the &lt;code&gt;,&lt;/code&gt; character, and extract the first column with &lt;code&gt;-f 1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We could also select both the first and second columns by using the&lt;code&gt;-f 1,2&lt;/code&gt; option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 5 metadata.csv | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; , &lt;span class="nt"&gt;-f&lt;/span&gt; 1,2
mysql.performance.user_time,gauge
mysql.replication.seconds_behind_master,gauge
mysql.replication.slave_running,gauge
mysql.replication.slaves_connected,gauge
mysql.performance.queries,gauge
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a id="paste"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;paste&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;paste&lt;/code&gt; can merge together two different files into one multi-column file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;ingredients
eggs
milk
butter
tomatoes
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;prices
1&lt;span class="err"&gt;$&lt;/span&gt;
1.99&lt;span class="err"&gt;$&lt;/span&gt;
1.50&lt;span class="err"&gt;$&lt;/span&gt;
2&lt;span class="nv"&gt;$/&lt;/span&gt;kg
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;paste &lt;/span&gt;ingredients prices
eggs 1&lt;span class="err"&gt;$&lt;/span&gt;
milk 1.99&lt;span class="err"&gt;$&lt;/span&gt;
butter 1.50&lt;span class="err"&gt;$&lt;/span&gt;
tomatoes 2&lt;span class="nv"&gt;$/&lt;/span&gt;kg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By default, &lt;code&gt;paste&lt;/code&gt; uses a tab delimiter, but you can change that using the &lt;code&gt;-d&lt;/code&gt; option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;paste &lt;/span&gt;ingredients prices &lt;span class="nt"&gt;-d&lt;/span&gt;:
eggs:1&lt;span class="err"&gt;$&lt;/span&gt;
milk:1.99&lt;span class="err"&gt;$&lt;/span&gt;
butter:1.50&lt;span class="err"&gt;$&lt;/span&gt;
tomatoes:2&lt;span class="nv"&gt;$/&lt;/span&gt;kg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Another common use of &lt;code&gt;paste&lt;/code&gt; it to join all lines within a stream or a file using a given delimiter, using a combination of the &lt;code&gt;-s&lt;/code&gt; and &lt;code&gt;-d&lt;/code&gt;argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;paste&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;, ingredients
eggs,milk,butter,tomatoes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;-&lt;/code&gt; is specified as an input file, &lt;code&gt;stdin&lt;/code&gt; will be read instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;ingredients | &lt;span class="nb"&gt;paste&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;, -
eggs,milk,butter,tomatoes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a id="sort"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;sort&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;sort&lt;/code&gt;, well, sorts argument files or input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;ingredients
eggs
milk
butter
tomatoes
salt
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sort &lt;/span&gt;ingredients
butter
eggs
milk
salt
tomatoes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;sort -r&lt;/code&gt; performs a reverse sort.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; ingredients
tomatoes
salt
milk
eggs
butter
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;sort -n&lt;/code&gt; performs a numerical sort, by sorting fields by their arithmetic value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;numbers
0
2
1
10
3
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sort &lt;/span&gt;numbers
0
1
10
2
3
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; numbers
0
1
2
3
10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a id="uniq"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;uniq&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;uniq&lt;/code&gt; detects or filters out adjacent identical lines in its argument file or input stream.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;duplicates
and one
and one
and two
and one
and two
and one, two, three
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;uniq &lt;/span&gt;duplicates
and one
and two
and one
and two
and one, two, three
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As &lt;code&gt;uniq&lt;/code&gt; only filters out &lt;em&gt;adjacent&lt;/em&gt; identical lines, we can still see more than one unique lines in its output. To filter out all identical lines from our &lt;code&gt;duplicates&lt;/code&gt; file, we need to sort its content first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sort &lt;/span&gt;duplicates | &lt;span class="nb"&gt;uniq
&lt;/span&gt;and one
and one, two, three
and two
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;uniq -c&lt;/code&gt; prepends all lines with its number of occurrences.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sort &lt;/span&gt;duplicates | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt;
   3 and one
   1 and one, two, three
   2 and two
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;uniq -u&lt;/code&gt; only displays the unique lines within its input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sort &lt;/span&gt;duplicates | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;
and one, two, three
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;uniq&lt;/code&gt; is particularly useful used in conjunction with &lt;code&gt;sort&lt;/code&gt;, as&lt;code&gt;| sort | uniq&lt;/code&gt; allows you to remove any duplicate line in a file or a stream.&lt;/p&gt;

&lt;p&gt;&lt;a id="awk"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;awk&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;awk&lt;/code&gt; is a little more than a text processing tool: it’s actually a whole &lt;a href="https://www.gnu.org/software/gawk/manual/gawk.html"&gt;programming language&lt;/a&gt; of its own. One thing &lt;code&gt;awk&lt;/code&gt; is &lt;em&gt;really&lt;/em&gt; good at is splitting files into columns, and it especially shines when these files contain a mix and match of spaces and tabs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; multi-columns
John Smith    Doctor^ITardis
Sarah-James Smith^I    Companion^ILondon
Rose Tyler   Companion^ILondon
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note: &lt;code&gt;cat -t&lt;/code&gt; displays tabs as &lt;code&gt;^I&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can see that these columns are either separated by spaces or tabs,and that they are not always separated by the same number of spaces.&lt;code&gt;cut&lt;/code&gt; would be of no use there, because it only works on a single character delimiter. &lt;code&gt;awk&lt;/code&gt; however, can easily make sense of that file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;awk '{ print $n }'&lt;/code&gt; prints the nth column in the text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;multi-columns | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ print $1 }'&lt;/span&gt;
John
Sarah-James
Rose
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;multi-columns | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ print $3 }'&lt;/span&gt;
Doctor
Companion
Companion
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;multi-columns | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ print $1,$2 }'&lt;/span&gt;
John Smith
Sarah-James Smith
Rose Tyler
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There is so much more we can do with &lt;code&gt;awk&lt;/code&gt;, however, printing columnsprobably accounts for 99% of my personal usage.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{ print $NF }&lt;/code&gt; prints the last column in the line.&lt;/p&gt;

&lt;p&gt;&lt;a id="tr"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;tr&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;tr&lt;/code&gt; stands for &lt;em&gt;translate&lt;/em&gt;, and it replaces characters into others. It either works on characters or character &lt;em&gt;classes&lt;/em&gt;, such as lowercase,printable, spaces, alphanumeric, etc.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tr &amp;lt;char1&amp;gt; &amp;lt;char2&amp;gt;&lt;/code&gt; translates all occurrences of &lt;code&gt;&amp;lt;char1&amp;gt;&lt;/code&gt; from its standard input into &lt;code&gt;&amp;lt;char2&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Computers are fast"&lt;/span&gt; | &lt;span class="nb"&gt;tr &lt;/span&gt;a A
computers Are fAst
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;tr&lt;/code&gt; can also translate character classes by using the &lt;code&gt;[:class:]&lt;/code&gt;notation. The full list of available classes is described in the &lt;code&gt;tr&lt;/code&gt;man page, but we’ll demonstrate some of them here.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[:space:]&lt;/code&gt; represent all types of spaces, from a simple space, to a tabor a newline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"computers are fast"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'[:space:]'&lt;/span&gt; &lt;span class="s1"&gt;','&lt;/span&gt;
computers,are,fast,%
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All spaces-like characters were translated into a comma. Note that the&lt;code&gt;%&lt;/code&gt; character at the end of the output represents the lack of a trailing newline. Indeed, that newline was translated to a comma as well.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[:lower:]&lt;/code&gt; represents all lowercase characters, and &lt;code&gt;[:upper:]&lt;/code&gt;represents all uppercase characters. Converting between cases is thus made very easy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"computers are fast"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'[:lower:]'&lt;/span&gt; &lt;span class="s1"&gt;'[:upper:]'&lt;/span&gt;
COMPUTERS ARE FAST
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"COMPUTERS ARE FAST"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'[:upper:]'&lt;/span&gt; &lt;span class="s1"&gt;'[:lower:]'&lt;/span&gt;
computers are fast
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;tr -c SET1 SET2&lt;/code&gt; will transform any character &lt;em&gt;not&lt;/em&gt; in SET1 into the characters in SET2. The following example replaces all non vowels by spaces.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"computers are fast"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'[aeiouy]'&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt;
 o  u e   a e  a
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;tr -d&lt;/code&gt; deletes the matched characters, instead of replacing them. It’s the equivalent of &lt;code&gt;tr &amp;lt;char&amp;gt; ''&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"computers are fast"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'[aeiouy]'&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt;
 o  u e   a e  a
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;tr&lt;/code&gt; can also replace character ranges, for example all letters between_a_ and &lt;em&gt;e&lt;/em&gt;, or all numbers between 1 and 8, by using the notation&lt;code&gt;s-e&lt;/code&gt;, where &lt;code&gt;s&lt;/code&gt; is the start character and &lt;code&gt;e&lt;/code&gt; is the end one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"computers are fast"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'a-e'&lt;/span&gt; &lt;span class="s1"&gt;'x'&lt;/span&gt;
xomputxrs xrx fxst
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"5uch l337 5p34k"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'1-4'&lt;/span&gt; &lt;span class="s1"&gt;'x'&lt;/span&gt;
5uch lxx7 5pxxk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;tr -s string1&lt;/code&gt; compresses any multiple occurrences of the characters in &lt;code&gt;string1&lt;/code&gt; into a single one. One of the most useful uses of &lt;code&gt;tr -s&lt;/code&gt; is to replace multiple consecutive spaces by a single one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Computers         are       fast"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt;
Computers are fast
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a id="fold"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;fold&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;fold&lt;/code&gt; wraps each input line to fit in a specified width. It can be useful to make sure an argument text fits in a small display size for example. &lt;code&gt;fold -w n&lt;/code&gt; folds the lines at &lt;code&gt;n&lt;/code&gt; characters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/Documents/readme | &lt;span class="nb"&gt;fold&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; 16
Thanks again &lt;span class="k"&gt;for
 &lt;/span&gt;reading this bo
ok!
I hope you&lt;span class="s1"&gt;'re fo
llowing so far!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;fold -s&lt;/code&gt; will only break lines on a space character, and can be combined with &lt;code&gt;-w&lt;/code&gt; to fold up to a given number of characters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/Documents/readme | &lt;span class="nb"&gt;fold&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; 16 &lt;span class="nt"&gt;-s&lt;/span&gt;
Thanks again
&lt;span class="k"&gt;for &lt;/span&gt;reading
this book!
I hope you&lt;span class="s1"&gt;'re
following so
far!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a id="sed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;sed&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;sed&lt;/code&gt; is a non-interactive stream editor, used to perform text transformation on its input stream, on a line-per-line basis. It can take its output from a file our its &lt;code&gt;stdin&lt;/code&gt; and will output its result either in a file or its &lt;code&gt;stdout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It works by taking one or many optional &lt;em&gt;addresses&lt;/em&gt;, a &lt;em&gt;function&lt;/em&gt; and &lt;em&gt;parameters&lt;/em&gt;. A &lt;code&gt;sed&lt;/code&gt; command thus looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[address[,address]]function[arguments]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;While &lt;code&gt;sed&lt;/code&gt; can perform many functions, we will cover only substitution, as it is probably &lt;code&gt;sed&lt;/code&gt;'s most common use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Substituting text
&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;sed&lt;/code&gt; substitution command looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;s/PATTERN/REPLACEMENT/[options]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: replacing the first instance of a word for each line in a file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;hello
hello hello
hello world!
hi
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;hello | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/hello/Hey I just met you/'&lt;/span&gt;
Hey I just met you hello
Hey I just met you world
hi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can see that only the first occurrence of &lt;code&gt;hello&lt;/code&gt; was replaced in the first line. To  replace &lt;em&gt;all&lt;/em&gt; occurrences of &lt;code&gt;hello&lt;/code&gt; in each line, we can use the &lt;code&gt;g&lt;/code&gt; (for &lt;em&gt;global&lt;/em&gt;) option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;hello | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/hello/Hey I just met you/g'&lt;/span&gt;
Hey I just met you Hey I just met you
Hey I just met you world
hi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;sed&lt;/code&gt; allows you to specify any other separator than &lt;code&gt;/&lt;/code&gt;, which is especially useful to keep the command readable if the search of replacement pattern contains forward slashes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;hello | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s@hello@Hey I just met you@g'&lt;/span&gt;
Hey I just met you Hey I just met you
Hey I just met you world
hi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By specifying an address, we can tell sed on which line or line-range to actually perform the substitution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;hello | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'1s/hello/Hey I just met you/g'&lt;/span&gt;
Hey I just met you hello
hello world
hi
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;hello | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'2s/hello/Hey I just met you/g'&lt;/span&gt;
hello hello
Hey I just met you  world
hi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The address &lt;code&gt;1&lt;/code&gt; tells &lt;code&gt;sed&lt;/code&gt; to only replace &lt;code&gt;hello&lt;/code&gt; by &lt;code&gt;Hey I just met you&lt;/code&gt; on line 1. We can specify an address range with the notation &lt;code&gt;&amp;lt;start&amp;gt;,&amp;lt;end&amp;gt;&lt;/code&gt; where &lt;code&gt;&amp;lt;end&amp;gt;&lt;/code&gt; can either be a line number or &lt;code&gt;$&lt;/code&gt;, meaning the last line in the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;hello | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'1,2s/hello/Hey I just met you/g'&lt;/span&gt;
Hey I just met you Hey I just met you
Hey I just met you world
hi
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;hello | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'2,3s/hello/Hey I just met you/g'&lt;/span&gt;
hello hello
Hey I just met you world
hi
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;hello | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'2,$s/hello/Hey I just met you/g'&lt;/span&gt;
hello hello
Hey I just met you world
hi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By default, &lt;code&gt;sed&lt;/code&gt; displays its result in its &lt;code&gt;stdout&lt;/code&gt;, but it can also edit the initial file in-place, with the use of the &lt;code&gt;-i&lt;/code&gt; option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; &lt;span class="s1"&gt;'s/hello/Bonjour/'&lt;/span&gt; sed-data
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;sed-data
Bonjour hello
Bonjour world
hi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: On Linux, only &lt;code&gt;-i&lt;/code&gt; needs to be specified. However, due to the fact that &lt;code&gt;sed&lt;/code&gt;'s behavior on macOS is slightly different, the &lt;code&gt;''&lt;/code&gt; needs to be added right after &lt;code&gt;-i&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; gauge metadata.csv | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt;, &lt;span class="s1"&gt;'{ if ($4 == "query") { print $1, "per", $5 } }'&lt;/span&gt;
mysql.performance.com_delete per second
mysql.performance.com_delete_multi per second
mysql.performance.com_insert per second
mysql.performance.com_insert_select per second
mysql.performance.com_replace_select per second
mysql.performance.com_select per second
mysql.performance.com_update per second
mysql.performance.com_update_multi per second
mysql.performance.questions per second
mysql.performance.slow_queries per second
mysql.performance.queries per second
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This example filters the lines containing the word &lt;code&gt;gauge&lt;/code&gt; in our &lt;code&gt;metadata.csv&lt;/code&gt; file using &lt;code&gt;grep&lt;/code&gt;, then the filters the lines with the string &lt;code&gt;query&lt;/code&gt; as their 4th column, and displays the metric name (1st column) with its associated &lt;code&gt;per_unit_name&lt;/code&gt; value (5th column).&lt;/p&gt;

&lt;h3&gt;
  
  
  Printing the IPv4 address associated with a network interface
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ifconfig en0 | &lt;span class="nb"&gt;grep &lt;/span&gt;inet | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; inet6 | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ print $2 }'&lt;/span&gt;
192.168.0.38
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ifconfig &amp;lt;interface name&amp;gt;&lt;/code&gt; prints details associated with the argument network interface name. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;en0: &lt;span class="nv"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8863&amp;lt;UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST&amp;gt; mtu 1500
    ether 19:64:92:de:20:ba
    inet6 fe80::8a3:a1cb:56ae:7c7c%en0 prefixlen 64 secured scopeid 0x7
    inet 192.168.0.38 netmask 0xffffff00 broadcast 192.168.0.255
    nd6 &lt;span class="nv"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;201&amp;lt;PERFORMNUD,DAD&amp;gt;
    media: autoselect
    status: active
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We then &lt;code&gt;grep&lt;/code&gt; for &lt;code&gt;inet&lt;/code&gt;, which will match 2 lines.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ifconfig en0 | &lt;span class="nb"&gt;grep &lt;/span&gt;inet
    inet6 fe80::8a3:a1cb:56ae:7c7c%en0 prefixlen 64 secured scopeid 0x7
    inet 192.168.0.38 netmask 0xffffff00 broadcast 192.168.0.255
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We then exclude the line with &lt;code&gt;ipv6&lt;/code&gt; by using a &lt;code&gt;grep -v&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ifconfig en0 | &lt;span class="nb"&gt;grep &lt;/span&gt;inet | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; inet6
inet 192.168.0.38 netmask 0xffffff00 broadcast 192.168.0.255
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We finally use &lt;code&gt;awk&lt;/code&gt; to get the 2nd column in that line: the IPv4 address associated with our &lt;code&gt;en0&lt;/code&gt; network interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ifconfig en0 | &lt;span class="nb"&gt;grep &lt;/span&gt;inet | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; inet6 | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ print $2 }'&lt;/span&gt;
192.168.0.38
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Extracting a value from a config file
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'editor ='&lt;/span&gt; ~/.gitconfig  | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-f2&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/ //g'&lt;/span&gt;
/usr/bin/vim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We look for the &lt;code&gt;editor =&lt;/code&gt; value in the current user's git configuration file, then cut over the &lt;code&gt;=&lt;/code&gt; sign, get the second column and remove any space around that column.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'editor ='&lt;/span&gt; ~/.gitconfig
     editor &lt;span class="o"&gt;=&lt;/span&gt; /usr/bin/vim
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'editor ='&lt;/span&gt; ~/.gitconfig  | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="s1"&gt;'='&lt;/span&gt; &lt;span class="nt"&gt;-f2&lt;/span&gt;
 /usr/bin/vim
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'editor ='&lt;/span&gt; ~/.gitconfig  | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="s1"&gt;'='&lt;/span&gt; &lt;span class="nt"&gt;-f2&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/ //'&lt;/span&gt;
/usr/bin/vim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Extracting IP addresses from a log file
&lt;/h3&gt;

&lt;p&gt;The following real life example looks for the message &lt;code&gt;Too many connections from&lt;/code&gt; in a database log file (which is followed by an IP address) and displays the 10 biggest offenders.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'Too many connections from'&lt;/span&gt; db.log | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ print $12 }'&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s@/@@'&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 10 | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ print $2 }'&lt;/span&gt;
   10.11.112.108
   10.11.111.70
   10.11.97.57
   10.11.109.72
   10.11.116.156
   10.11.100.221
   10.11.96.242
   10.11.81.68
   10.11.99.112
   10.11.107.120
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's break down what this pipeline of command does. First, let's look at what a log line looks like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"Too many connections from"&lt;/span&gt; db.log | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1
2020-01-01 08:02:37,617 &lt;span class="o"&gt;[&lt;/span&gt;myid:1] - WARN  &lt;span class="o"&gt;[&lt;/span&gt;NIOServerCxn.Factory:1.2.3.4/1.2.3.4:2181:NIOServerCnxnFactory@193] - Too many connections from /10.11.112.108 - max is 60
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;awk '{ print $12 }'&lt;/code&gt; then extracts the IP from the line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"Too many connections from"&lt;/span&gt; db.log | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ print $12 }'&lt;/span&gt;
/10.11.112.108
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;sed 's@/@@'&lt;/code&gt; removes the trailing slash from the IPs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"Too many connections from"&lt;/span&gt; db.log | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ print $12 }'&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s@/@@'&lt;/span&gt;
10.11.112.108
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: As we have previously seen, we can use whatever separator we want for &lt;code&gt;sed&lt;/code&gt;. While &lt;code&gt;/&lt;/code&gt; is commonly used as a separator, we are currently replacing that very character, which would make the substitution expression sightly less readable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/\///'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;sort | uniq -c&lt;/code&gt;  sorts the IPs lexicographically, and then removed duplicates while prefixing IPs by their associated number of occurrences.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'Too many connections from'&lt;/span&gt; db.log | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ print $12 }'&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s@/@@'&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt;
   1379 10.11.100.221
   1213 10.11.103.168
   1138 10.11.105.177
    946 10.11.106.213
   1211 10.11.106.4
   1326 10.11.107.120
   ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;sort -rn | head -n 10&lt;/code&gt; sorts the lines by the number of occurrences, numerically and in the reversed order, which displays the biggest offenders first, 10 of which are displayed. The final &lt;code&gt;awk { print $2 }&lt;/code&gt; extracts the IPs themselves.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'Too many connections from'&lt;/span&gt; db.log | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ print $12 }'&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s@/@@'&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 10 | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ print $2 }'&lt;/span&gt;
  10.11.112.108
  10.11.111.70
  10.11.97.57
  10.11.109.72
  10.11.116.156
  10.11.100.221
  10.11.96.242
  10.11.81.68
  10.11.99.112
  10.11.107.120
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Renaming a function in a source file
&lt;/h3&gt;

&lt;p&gt;Let's imagine that we are working a code project, and we would like to rename rename a poorly named function (or class, variable, etc) in a code file. We can do this by using &lt;code&gt;sed -i&lt;/code&gt;, which performs an in-place replacement in a file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;izk/utils.py
def bool_from_str&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;:
    &lt;span class="k"&gt;if &lt;/span&gt;s.isdigit&lt;span class="o"&gt;()&lt;/span&gt;:
        &lt;span class="k"&gt;return &lt;/span&gt;int&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; 1
    &lt;span class="k"&gt;return &lt;/span&gt;s.lower&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'yes'&lt;/span&gt;, &lt;span class="s1"&gt;'true'&lt;/span&gt;, &lt;span class="s1"&gt;'y'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/def bool_from_str/def is_affirmative/'&lt;/span&gt; izk/utils.py
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;izk/utils.py
def is_affirmative&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;:
    &lt;span class="k"&gt;if &lt;/span&gt;s.isdigit&lt;span class="o"&gt;()&lt;/span&gt;:
        &lt;span class="k"&gt;return &lt;/span&gt;int&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; 1
    &lt;span class="k"&gt;return &lt;/span&gt;s.lower&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'yes'&lt;/span&gt;, &lt;span class="s1"&gt;'true'&lt;/span&gt;, &lt;span class="s1"&gt;'y'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Use &lt;code&gt;sed -i ''&lt;/code&gt; instead of &lt;code&gt;sed -i&lt;/code&gt; on macOs, as the &lt;code&gt;sed&lt;/code&gt; version behaves slightly differently.&lt;/p&gt;

&lt;p&gt;We've however only renamed this function in the file it was defined in. Any other file we import &lt;code&gt;bool_from_str&lt;/code&gt; will now be broken, as this function is not defined anymore. We'd need a way to rename &lt;code&gt;bool_from_str&lt;/code&gt; everywhere it is found in our project. We can achieve just that by using &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;sed&lt;/code&gt;, and either &lt;code&gt;for&lt;/code&gt; loops or &lt;code&gt;xargs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a id="going-further-for-loops-and-xargs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Going further: &lt;code&gt;for&lt;/code&gt; loops and &lt;code&gt;xargs&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;To replace all occurrences of &lt;code&gt;bool_from_str&lt;/code&gt; in our project, we first need to recursively find them using &lt;code&gt;grep -r&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; bool_from_str &lt;span class="nb"&gt;.&lt;/span&gt;
./tests/test_utils.py:from izk.utils import bool_from_str
./tests/test_utils.py:def test_bool_from_str&lt;span class="o"&gt;(&lt;/span&gt;s, expected&lt;span class="o"&gt;)&lt;/span&gt;:
./tests/test_utils.py:    assert bool_from_str&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; expected
./izk/utils.py:def bool_from_str&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;:
./izk/prompt.py:from .utils import bool_from_str
./izk/prompt.py:                    default &lt;span class="o"&gt;=&lt;/span&gt; bool_from_str&lt;span class="o"&gt;(&lt;/span&gt;os.environ[envvar]&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As we are only interested in the matching files, we also need to use the &lt;code&gt;-l/--files-with-matches&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-l, --files-with-matches
        Only the names of files containing selected lines are written to standard out-
        put.  grep will only search a file until a match has been found, making
        searches potentially less expensive.  Pathnames are listed once per file
        searched.  If the standard input is searched, the string ``(standard input)''
        is written.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;--files-with-matches&lt;/span&gt; bool_from_str &lt;span class="nb"&gt;.&lt;/span&gt;
./tests/test_utils.py
./izk/utils.py
./izk/prompt.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can then use the &lt;code&gt;xargs&lt;/code&gt; command to perform an action of each line in the output (each file containing the &lt;code&gt;bool_from_str&lt;/code&gt; string).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;--files-with-matches&lt;/span&gt; bool_from_str &lt;span class="nb"&gt;.&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  xargs &lt;span class="nt"&gt;-n&lt;/span&gt; 1 &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/bool_from_str/is_affirmative/'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-n 1&lt;/code&gt; tells &lt;code&gt;xargs&lt;/code&gt; that each line in the output should cause a separate &lt;code&gt;sed&lt;/code&gt; command to be executed.&lt;/p&gt;

&lt;p&gt;The following commands were then executed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/bool_from_str/is_affirmative/'&lt;/span&gt; ./tests/test_utils.py
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/bool_from_str/is_affirmative/'&lt;/span&gt; ./izk/utils.py
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/bool_from_str/is_affirmative/'&lt;/span&gt; ./izk/prompt.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If the command you call with &lt;code&gt;xargs&lt;/code&gt; (&lt;code&gt;sed&lt;/code&gt;, in our case) support multiple arguments, you can drop the &lt;code&gt;-n 1&lt;/code&gt; argument and run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;--files-with-matches&lt;/span&gt; bool_from_str &lt;span class="nb"&gt;.&lt;/span&gt; | xargs &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/bool_from_str/is_affirmative/'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;which will then execute&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/bool_from_str/is_affirmative/'&lt;/span&gt; ./tests/test_utils.py ./izk/utils.py ./izk/prompt.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;:&lt;br&gt;
We can see that &lt;code&gt;sed&lt;/code&gt; can take multiple arguments by looking at its synopsis, in its &lt;code&gt;man&lt;/code&gt; page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SYNOPSIS
     sed [-Ealn] command [file ...]
     sed [-Ealn] [-e command] [-f command_file] [-i extension] [file ...]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Indeed, as we've seen in the previous chapter, &lt;code&gt;file ...&lt;/code&gt; means that multiple arguments representing file names are accepted.&lt;/p&gt;

&lt;p&gt;We can see that all &lt;code&gt;bool_from_str&lt;/code&gt; occurrences have been replaced.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; is_affirmative &lt;span class="nb"&gt;.&lt;/span&gt;
./tests/test_utils.py:from izk.utils import is_affirmative
./tests/test_utils.py:def test_is_affirmative&lt;span class="o"&gt;(&lt;/span&gt;s, expected&lt;span class="o"&gt;)&lt;/span&gt;:
./tests/test_utils.py:    assert is_affirmative&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; expected
./izk/utils.py:def is_affirmative&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;:
./izk/prompt.py:from .utils import is_affirmative
./izk/prompt.py:                    default &lt;span class="o"&gt;=&lt;/span&gt; is_affirmative&lt;span class="o"&gt;(&lt;/span&gt;os.environ[envvar]&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As it is often the case, there are multiple ways of achieving the same result. Instead of using &lt;code&gt;xargs&lt;/code&gt;, we could have used &lt;code&gt;for&lt;/code&gt; lops, which allow you to iterate over a list of lines and perform an action on each element. These &lt;code&gt;for&lt;/code&gt; loops have the following syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;item &lt;span class="k"&gt;in &lt;/span&gt;list&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By wrapping our &lt;code&gt;grep&lt;/code&gt; command by &lt;code&gt;$()&lt;/code&gt;, it will cause the shell to execute the it in a &lt;em&gt;subshell&lt;/em&gt;, which result will then be iterated on by the &lt;code&gt;for&lt;/code&gt; loop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;file &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;--files-with-matches&lt;/span&gt; bool_from_str .&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/bool_from_str/is_affirmative/'&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;which will execute&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/bool_from_str/is_affirmative/'&lt;/span&gt; ./tests/test_utils.py
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/bool_from_str/is_affirmative/'&lt;/span&gt; ./izk/utils.py
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/bool_from_str/is_affirmative/'&lt;/span&gt; ./izk/prompt.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I tend to find the for loop syntax clearer than &lt;code&gt;xargs&lt;/code&gt;'s. &lt;code&gt;xargs&lt;/code&gt; can however execute the commands in parallel using its &lt;code&gt;-P n&lt;/code&gt; options, where &lt;code&gt;n&lt;/code&gt; is the maximum number of parallel commands to be executed at a time, which can be a performance win if your command takes time to run.&lt;/p&gt;

&lt;p&gt;&lt;a id="summary"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;All these tools open up a world of possibilities, as allow you to extract data and transform its format, to make it possible to build entire workflows of commands that were possibly never intended to work together. Each of these commands accomplishes has a relatively small function (&lt;code&gt;sort&lt;/code&gt; sorts, &lt;code&gt;cat&lt;/code&gt; concatenates, &lt;code&gt;grep&lt;/code&gt; filters, &lt;code&gt;sed&lt;/code&gt; edits, &lt;code&gt;cut&lt;/code&gt; cuts, etc).&lt;/p&gt;

&lt;p&gt;Any given task involving text, can then be reduced to a pipeline of smaller tasks, each of them performing a simple action and piping their output into the next task.&lt;/p&gt;

&lt;p&gt;For example, if we wanted to know how many unique IPs could be found in a log file, and that these IPs always appeared at the same column, we could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;grep&lt;/code&gt; lines on a pattern specific to lines containing an IP address&lt;/li&gt;
&lt;li&gt;locate the column the IPs appear, and extract them with &lt;code&gt;awk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;sort the list of IPs with &lt;code&gt;sort&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;compute the list of &lt;em&gt;unique&lt;/em&gt; IPs with &lt;code&gt;uniq&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;count the number of lines (aka, of unique IPs) with &lt;code&gt;wc -l&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As there is a plethora of text processing tools, either available by default or installable, there is bound to be many ways to solve any given task.&lt;/p&gt;

&lt;p&gt;The examples in this article were contrived, but I suggest you read the amazing article &lt;a href="https://adamdrake.com/command-line-tools-can-be-235x-faster-than-your-hadoop-cluster.html"&gt;Command-line Tools can be 235x Faster than your Hadoop Cluster&lt;/a&gt; to get a sense of how useful and powerful these text processing commands really are, and what real-life problems they can solve.&lt;/p&gt;

&lt;p&gt;&lt;a id="exercices"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Exercices
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;2.1&lt;/strong&gt;: Count the number of files and directories located in your home directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.2&lt;/strong&gt;: Display the content of a file in all caps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.3&lt;/strong&gt;: Count how many times each word was found in a file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.4&lt;/strong&gt;: Count the number of vowels present in a file. Display the result from the most common to the least.&lt;/p&gt;




&lt;p&gt;
&lt;em&gt;Essential Tools and Practices for the Aspiring Software Developer&lt;/em&gt; is a self-published book project by Balthazar Rouberol and &lt;a href="https://etnbrd.com"&gt;Etienne Brodu&lt;/a&gt;, ex-roommates, friends and colleagues, aiming at empowering the up and coming generation of developers. We currently are hard at work on it!
&lt;/p&gt;

&lt;p&gt;The book will help you set up a productive development environment and get acquainted with tools and practices that, along with your programming languages of choice, will go a long way in helping you grow as a software developer.
  It will cover subjects such as mastering the terminal, configuring and getting productive in a shell, the basics of code versioning with &lt;code&gt;git&lt;/code&gt;, SQL basics, tools such as &lt;code&gt;Make&lt;/code&gt;, &lt;code&gt;jq&lt;/code&gt; and regular expressions, networking basics as well as software engineering and collaboration best practices.
&lt;/p&gt;

&lt;p&gt;
  If you are interested in the project, we invite you to join the &lt;a href="https://balthazar-rouberol.us4.list-manage.com/subscribe?u=1f6080d496af07a836270ff1d&amp;amp;id=81ebd36adb"&gt;mailing list&lt;/a&gt;!
&lt;/p&gt;




&lt;p&gt;1.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://homepage.cs.uri.edu/~thenry/resources/unix_art/ch01s06.html"&gt;https://homepage.cs.uri.edu/~thenry/resources/unix_art/ch01s06.html&lt;/a&gt; ↩&lt;/p&gt;

</description>
      <category>bash</category>
      <category>tutorial</category>
      <category>linux</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Discovering the terminal</title>
      <dc:creator>Balthazar Rouberol</dc:creator>
      <pubDate>Sat, 14 Mar 2020 22:25:03 +0000</pubDate>
      <link>https://dev.to/brouberol/discovering-the-terminal-5ddf</link>
      <guid>https://dev.to/brouberol/discovering-the-terminal-5ddf</guid>
      <description>&lt;p&gt;Originally posted on my &lt;a href="https://blog.balthazar-rouberol.com/discovering-the-terminal"&gt;blog&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is a terminal?&lt;/li&gt;
&lt;li&gt;Your first steps&lt;/li&gt;
&lt;li&gt;Managing files&lt;/li&gt;
&lt;li&gt;Learning new options&lt;/li&gt;
&lt;li&gt;Command Input/Output streams&lt;/li&gt;
&lt;li&gt;Composing commands&lt;/li&gt;
&lt;li&gt;Escaping from bad situations&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;li&gt;Going further&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Discovering the terminal
&lt;/h1&gt;

&lt;p&gt;When people picture a programmer, it’s not uncommon for them to imagine&lt;br&gt;
someone sitting in front of a computer screen displaying undecipherable&lt;br&gt;
streams of text going by really fast, like in The Matrix. Let’s set the&lt;br&gt;
record straight. This is not true, at least for the most part. The&lt;br&gt;
Matrix however got some things right. A programmer works with &lt;em&gt;code&lt;/em&gt;,&lt;br&gt;
which, as its name indicates, has to be learned before it can be&lt;br&gt;
understood. Anyone not versed in the trade of reading and writing code&lt;br&gt;
would only see gibberish. Another thing these movies usually get right&lt;br&gt;
is the fact that a programmer types commands in a &lt;em&gt;terminal&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a id="what-is-a-terminal"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What is a terminal?
&lt;/h2&gt;

&lt;p&gt;Most of the applications people use everyday have a &lt;span class="gls"&gt;Graphical User Interface (GUI)&lt;/span&gt;. Think about Photoshop,&lt;br&gt;
Firefox, or your smartphone apps. These application have immense&lt;br&gt;
capabilities, but the user is mostly bound by the features implemented&lt;br&gt;
in them in the first place. What if you suddenly wanted to have a new&lt;br&gt;
feature in Photoshop that just wasn’t available? You would possibly end&lt;br&gt;
up either waiting for the newest version to be released, or have to&lt;br&gt;
install another application altogether.&lt;/p&gt;

&lt;p&gt;One of the most important tools in a programmer toolbox is of a&lt;br&gt;
different kind though. It’s called the &lt;em&gt;&lt;span class="gls"&gt;terminal&lt;/span&gt;&lt;/em&gt;, which is a &lt;em&gt;&lt;span class="gls"&gt;command-line&lt;/span&gt; application&lt;/em&gt;. That is to say that you&lt;br&gt;
enter a command, your computer executes that command, and displays the&lt;br&gt;
output in the terminal.&lt;/p&gt;

&lt;p&gt;In other words, this is an applications in which you give your computer&lt;br&gt;
orders. If you know how to ask, your computer will be happy to comply.&lt;br&gt;
However, if you order it to do something stupid, it will obey.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;— You: “Computer, create that folder.”&lt;/p&gt;

&lt;p&gt;— Computer: “Sure.”&lt;/p&gt;

&lt;p&gt;— You: “Now put all the files on my Desktop in that new folder.”&lt;/p&gt;

&lt;p&gt;— Computer: “No problem.”&lt;/p&gt;

&lt;p&gt;— You: “Now delete that folder forever with everything inside.”&lt;/p&gt;

&lt;p&gt;— Computer: “Done.”&lt;/p&gt;

&lt;p&gt;— You: “Wait, no, my mistake, I want it back.”&lt;/p&gt;

&lt;p&gt;— Computer: “Sorry, it’s all gone, as you requested.”&lt;/p&gt;

&lt;p&gt;— You: “…”&lt;/p&gt;

&lt;p&gt;— Computer: “I’m not even sorry.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Never has this famous quote been more true:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;With great power come great responsibility&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Learning your way around a terminal really is a fundamental shift in how&lt;br&gt;
you usually interact with computers. Instead of working inside the&lt;br&gt;
boundaries of an application, a terminal gives you free and unlimited&lt;br&gt;
access to every part of the computer. The littles wheels are off, and&lt;br&gt;
you are only limited by the number of commands you know. Consequently,&lt;br&gt;
learning how to use the terminal will give you insights about how your&lt;br&gt;
computer works. Let’s see what we can do. We’ll start small, but trust&lt;br&gt;
me, it gets better.&lt;/p&gt;

&lt;p&gt;&lt;a id="your-first-steps"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Your first steps
&lt;/h2&gt;

&lt;p&gt;First off, let’s define a couple of words.&lt;/p&gt;

&lt;p&gt;A terminal is an application you can open on your computer, in which&lt;br&gt;
you’ll be able to type commands in a command line interface (CLI). When&lt;br&gt;
you hit the Enter key, the command will be executed by a&lt;br&gt;
shell, and the result is displayed back in the terminal.&lt;/p&gt;

&lt;p&gt;In the early days of computing, video terminals were actual physical&lt;br&gt;
devices, used to execute commands onto a remote computer that could take&lt;br&gt;
a whole room.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KXVWdqu9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/physical-terminal.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KXVWdqu9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/physical-terminal.png" alt="The DEC VT100, a physical video terminal dating back 1978"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;The DEC VT100, a physical video terminal dating back 1978&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Nowadays, terminals are programs run into a graphical window, emulating&lt;br&gt;
the behavior of the video terminals of old.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4lv5eyJW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/shell.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4lv5eyJW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/shell.png" alt="This is what a terminal looks like nowadays"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;This is what a terminal looks like nowadays.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Different operating systems come with different terminals and different&lt;br&gt;
shells pre-installed, but most common shell out there is certainly &lt;code&gt;bash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before we go any deeper, let’s open a terminal! The way you do this however depends on your operating system.&lt;/p&gt;
&lt;h3&gt;
  
  
  Opening a terminal
&lt;/h3&gt;
&lt;h4&gt;
  
  
  On MacOS
&lt;/h4&gt;

&lt;p&gt;Open the &lt;code&gt;Finder&lt;/code&gt; app, click on &lt;code&gt;Applications&lt;/code&gt; on the left pane, then&lt;br&gt;
enter the &lt;code&gt;Utilities&lt;/code&gt; directory, then execute the &lt;code&gt;Terminal&lt;/code&gt; app. You&lt;br&gt;
can also use the Spotlight search by clicking on the magnifying glass&lt;br&gt;
icon on the top right corner of your screen (or use the Cmd&lt;br&gt;
Space keyboard shortcut), and type &lt;code&gt;Terminal&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  On Linux
&lt;/h4&gt;

&lt;p&gt;Depending on the Linux distribution you use, it might come with XTerm,&lt;br&gt;
Gnome-Terminal or Konsole pre-installed. Look for any of these in your&lt;br&gt;
applications menu. A lot of Linux installation use the&lt;br&gt;
Ctrl - Alt - T keyboard shortcut to&lt;br&gt;
open a terminal window.&lt;/p&gt;
&lt;h4&gt;
  
  
  On Windows
&lt;/h4&gt;

&lt;p&gt;Windows is a special case: Linux and MacOS come with bash pre-installed, whereas Windows does not. It comes with 2 built-in shells: &lt;code&gt;cmd&lt;/code&gt; and &lt;code&gt;Powershell&lt;/code&gt;. The rest of this tutorial and its following chapters however assume you are running bash. The reason for that is that &lt;code&gt;bash&lt;/code&gt; is pretty much ubiquitous, whether it's on a personal workstations or on servers. On top of that, bash comes with a myriad of tools and commands that will be detailed in the next chapter.&lt;/p&gt;

&lt;p&gt;Fortunately, Windows 10 can now natively run bash since 2019 by using the &lt;em&gt;Windows Subsystem for Linux&lt;/em&gt; (WSL). We suggest you follow the instructions from this &lt;a href="https://itsfoss.com/install-bash-on-windows/"&gt;tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wPDdNGA8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/itsfoss.com/wp-content/uploads/2016/08/install-ubuntu-windows-10-linux-subsystem-10.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wPDdNGA8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/itsfoss.com/wp-content/uploads/2016/08/install-ubuntu-windows-10-linux-subsystem-10.jpeg" alt="Running bash on Windows is now possible"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;Running bash on Windows is now possible&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Running our first command
&lt;/h3&gt;

&lt;p&gt;When you open your terminal, the first thing you will see is a &lt;em&gt;&lt;span class="gls"&gt;prompt&lt;/span&gt;&lt;/em&gt;. It is what is displayed every&lt;br&gt;
time the shell is ready for its next order. It is common for the prompt&lt;br&gt;
to display information useful for the user. In my case, &lt;code&gt;br&lt;/code&gt; is my&lt;br&gt;
username, and &lt;code&gt;morenika&lt;/code&gt; is my computer’s name (its &lt;em&gt;&lt;span class="gls"&gt;hostname&lt;/span&gt;&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4lv5eyJW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/shell.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4lv5eyJW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/shell.png" alt="`br@morenika:~$` is my prompt"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;&lt;code&gt;br@morenika:~$&lt;/code&gt; is my prompt&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;The black rectangle is called a &lt;em&gt;cursor&lt;/em&gt;. It represents your current&lt;br&gt;
typing position.&lt;/p&gt;



What *your* prompt actually looks like depends on your operating system
and your shell. Don’t worry if it does not look exactly the same as the
one in the following examples.



&lt;p&gt;The first command we will run is &lt;code&gt;ls&lt;/code&gt; (which stands for &lt;em&gt;list&lt;br&gt;
directory&lt;/em&gt;). By default, that command lists all directories and files&lt;br&gt;
present in the directory we currently are located into. To run that&lt;br&gt;
command, we need to type &lt;code&gt;ls&lt;/code&gt; after the prompt, and then hit&lt;br&gt;
Enter&lt;/p&gt;

&lt;p&gt;The text that is displayed after our command and before the next prompt&lt;br&gt;
is the command’s &lt;em&gt;output&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;br@morenika:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls
&lt;/span&gt;Android                code       Downloads              Music
AndroidStudioProjects  Desktop    Dropbox                Pictures
bin                    Documents  Firefox_wallpaper.png  Videos
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;These are all the files and directories located in my personal directory&lt;br&gt;
(also called &lt;em&gt;&lt;span class="gls"&gt;home directory&lt;/span&gt;&lt;/em&gt;).&lt;br&gt;
Let’s open a graphical file explorer and check, just to be sure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UhHyTfGh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/home.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UhHyTfGh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/home.png" alt="As expected, we weren’t lied to"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;As expected, we weren’t lied to&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;The shell is sensitive to casing: a lower-case command is not the same&lt;br&gt;
thing as it’s upper case equivalent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;br@morenika:~&lt;span class="nv"&gt;$ &lt;/span&gt;LS
bash: LS: &lt;span class="nb"&gt;command &lt;/span&gt;not found
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As of now, we will ignore the &lt;code&gt;br@morenika:~$&lt;/code&gt; prompt prefix and will&lt;br&gt;
only use &lt;code&gt;$&lt;/code&gt;, to keep our examples short.&lt;/p&gt;
&lt;h3&gt;
  
  
  Commands arguments
&lt;/h3&gt;

&lt;p&gt;In our last example, we listed all files and directories located in my&lt;br&gt;
home directory. What if I wanted to list all files located in the &lt;code&gt;bin&lt;/code&gt;&lt;br&gt;
directory that we can see in the output? In that case, I could pass&lt;br&gt;
&lt;code&gt;bin&lt;/code&gt; as an &lt;em&gt;argument&lt;/em&gt; to the &lt;code&gt;ls&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;bin
bat            fix-vlc-size  lf          terraform  vpnconnect
clean-desktop  itresize      nightlight  tv-mode
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By passing the &lt;code&gt;bin&lt;/code&gt; argument to the &lt;code&gt;ls&lt;/code&gt; command, we told it where to&lt;br&gt;
look, and we thus changed its behavior. Note that it is possible to pass&lt;br&gt;
more than one argument to a command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;Android bin
Android:
Sdk

bin:
bat  clean-desktop  fix-vlc-size  itresize  lf  nightlight  terraform  tv-mode  vpnconnect
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In that example, we passed two arguments to &lt;code&gt;ls&lt;/code&gt;: &lt;code&gt;bin&lt;/code&gt; and &lt;code&gt;Android&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;ls&lt;/code&gt; then proceeded to list the content of each these 2 directories.&lt;/p&gt;

&lt;p&gt;Think about how you would have done that in a File explorer GUI. You&lt;br&gt;
probably would have gone into the first directory, then gone back to the&lt;br&gt;
parent directory and finally proceeded with the next directory. The&lt;br&gt;
terminal allows you to be more efficient.&lt;/p&gt;
&lt;h3&gt;
  
  
  Command options
&lt;/h3&gt;

&lt;p&gt;Now, let’s say I’d also like to see how big files located under &lt;code&gt;bin&lt;/code&gt;&lt;br&gt;
are. No problem! The &lt;code&gt;ls&lt;/code&gt; command has &lt;em&gt;options&lt;/em&gt; we can use to adjust its&lt;br&gt;
behavior. The &lt;code&gt;-s&lt;/code&gt; option causes &lt;code&gt;ls&lt;/code&gt; to display each file size, in&lt;br&gt;
kilobytes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; bin
total 52336
 4772 bat                4 itresize    44296 terraform
    4 clean-desktop   3244 lf              4 tv-mode
    4 fix-vlc-size       4 nightlight      4 vpnconnect
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;While this is nice, I’d prefer to see the file size in a human-readable&lt;br&gt;
unit. I can add the &lt;code&gt;-h&lt;/code&gt; option to further specify what &lt;code&gt;ls&lt;/code&gt; has to do.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; bin
total 52M
4.7M bat            4.0K itresize     44M terraform
4.0K clean-desktop  3.2M lf          4.0K tv-mode
4.0K fix-vlc-size   4.0K nightlight  4.0K vpnconnect
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I can separate both options with a space, or also group them as one&lt;br&gt;
option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-sh&lt;/span&gt; bin
total 52M
4.7M bat            4.0K itresize     44M terraform
4.0K clean-desktop  3.2M lf          4.0K tv-mode
4.0K fix-vlc-size   4.0K nightlight  4.0K vpnconnect
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I’d finally like each file and its associated size to be displayed on&lt;br&gt;
its own line. Enter the &lt;code&gt;-1&lt;/code&gt; option!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt; bin
total 52M
4.7M bat
4.0K clean-desktop
4.0K fix-vlc-size
4.0K itresize
3.2M lf
4.0K nightlight
 44M terraform
4.0K tv-mode
4.0K vpnconnect
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Short options make it easy to type a command quickly, but the result can&lt;br&gt;
be hard to decipher after a certain amount of options, and you might&lt;br&gt;
find yourself wondering that the command is doing in the first place.&lt;br&gt;
Luckily, options can have a &lt;em&gt;long form&lt;/em&gt; and a &lt;em&gt;short form&lt;/em&gt;. For example,&lt;br&gt;
&lt;code&gt;-s&lt;/code&gt; can be replaced by its long form &lt;code&gt;--size&lt;/code&gt;, and &lt;code&gt;-h&lt;/code&gt; by&lt;br&gt;
&lt;code&gt;--human-readable&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;--size&lt;/span&gt; &lt;span class="nt"&gt;--human-readable&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt; bin
total 52M
4.7M bat
4.0K clean-desktop
4.0K fix-vlc-size
4.0K itresize
3.2M lf
4.0K nightlight
 44M terraform
4.0K tv-mode
4.0K vpnconnect
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The command feels way more self-explanatory this way! You’ll notice that&lt;br&gt;
we still used the short form for the &lt;code&gt;-1&lt;/code&gt; option. The reason for that is&lt;br&gt;
that this option simply does not have a long form.&lt;/p&gt;
&lt;h3&gt;
  
  
  Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  A terminal is an application through which you interact with a shell&lt;/li&gt;
&lt;li&gt;  You can execute commands by typing them in the shell’s command-line
and hitting Enter
&lt;/li&gt;
&lt;li&gt;  A command can take 0, 1 or more arguments&lt;/li&gt;
&lt;li&gt;  A command’s behavior can be changed by passing options&lt;/li&gt;
&lt;li&gt;  By convention, options can have have multiple forms: a short and/or
a long one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o1WSxbRJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/terminal-parts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o1WSxbRJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/terminal-parts.png" alt="Here is a summary of the different parts of a command"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;Here is a summary of the different parts of a command&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="managing-files"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Managing files
&lt;/h2&gt;

&lt;p&gt;So far, we’ve seen how to run a command, changing its behavior by&lt;br&gt;
passing command-line arguments and options, and that &lt;code&gt;ls&lt;/code&gt; is used to&lt;br&gt;
list the content of a directory. It’s now time to learn about how to&lt;br&gt;
managing your files, by creating files and directories, copying and&lt;br&gt;
moving them around, creating links, etc. The goal of this section is to&lt;br&gt;
teach you how to do everything you usually do in your file explorer, but&lt;br&gt;
in your terminal.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;pwd&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt;: navigating between directories
&lt;/h3&gt;

&lt;p&gt;Up to now, every command we’ve run were executed from our &lt;em&gt;&lt;span class="gls"&gt;home directory&lt;/span&gt;&lt;/em&gt; (the directory in which&lt;br&gt;
you have all your documents, downloads, etc). The same way you can&lt;br&gt;
navigate directories in a graphical file editor, you can do it in a&lt;br&gt;
terminal as well.&lt;/p&gt;

&lt;p&gt;Before going anywhere, we first need to find know where we are. Enters&lt;br&gt;
&lt;code&gt;pwd&lt;/code&gt;, standing for &lt;em&gt;print working directory&lt;/em&gt;. This command displays&lt;br&gt;
your current working directory (&lt;em&gt;a.k.a&lt;/em&gt; where you are).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now that we found our bearings, we can finally move around. We&lt;br&gt;
can do that with the &lt;code&gt;cd&lt;/code&gt; command, standing for (you might have guessed&lt;br&gt;
it) &lt;em&gt;change directory&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;Documents
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br/Documents
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ./invoices
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br/Documents/invoices
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;2020
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br/Documents/invoices/2020
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As &lt;code&gt;2020&lt;/code&gt; is empty, we can’t go any further. However, we can also&lt;br&gt;
go back to the &lt;em&gt;parent directory&lt;/em&gt; (the directory containing the one we&lt;br&gt;
are currently into) using &lt;code&gt;cd ..&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br/Documents/invoices/2020
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br/Documents/invoices
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We don’t have to always change directory one level at the time. We can&lt;br&gt;
go up multiples directories at a time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br/Documents/invoices
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ../..
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can also go several directories down at the same time&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;Documents/invoices/2020
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;cd&lt;/code&gt; without arguments takes you back to your home directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br/Documents/invoices/2020
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;cd -&lt;/code&gt; takes you back to your previous location.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br/Documents/invoices/2020
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /home/br
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; -
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br/Documents/invoices/2020
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You might wonder why &lt;code&gt;cd ..&lt;/code&gt; takes you back to the parent directory?&lt;br&gt;
What does &lt;code&gt;..&lt;/code&gt; mean? To understand this, we need to explore how &lt;em&gt;paths&lt;/em&gt;&lt;br&gt;
work.&lt;/p&gt;
&lt;h3&gt;
  
  
  Paths: root, absolute and relative
&lt;/h3&gt;

&lt;p&gt;If you have never used a terminal before, and have only navigated&lt;br&gt;
between directories using a graphical file explorer, the notion of&lt;br&gt;
&lt;em&gt;path&lt;/em&gt; might be a bit foreign. A path is a unique location to a file or&lt;br&gt;
a folder on your file system. The easiest way to explain it is by&lt;br&gt;
describing how files and directories are organized on your disk.&lt;/p&gt;

&lt;p&gt;The base directory (also called &lt;span class="gls"&gt;root&lt;br&gt;
directory&lt;/span&gt;, and referred as &lt;code&gt;/&lt;/code&gt;) is the highest directory in the&lt;br&gt;
hierarchy: it contains every single other file and directory in your&lt;br&gt;
system, each of these directories possibly containing others, to form a&lt;br&gt;
structure looking like a tree.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yxdqa_Kf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/paths.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yxdqa_Kf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/paths.png" alt="Your disk is organized like a tree"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;Your disk is organized like a tree&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Let’s look a what that &lt;code&gt;/&lt;/code&gt; root directory contains.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; /
bin  boot  dev  etc  home  lib  lib64  lost+found  media
mnt opt  proc  root  run  sbin  srv  sys  tmp  usr  var
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ok so, there is a couple of things in there. We have talked about home&lt;br&gt;
directories before, remember? It turns out that all the users’ home&lt;br&gt;
directories are located under the &lt;code&gt;home&lt;/code&gt; directory. As &lt;code&gt;home&lt;/code&gt; is located&lt;br&gt;
under &lt;code&gt;/&lt;/code&gt;, we can refer it via its &lt;em&gt;&lt;span class="gls"&gt;absolute path&lt;/span&gt;&lt;/em&gt;, that is to say the full path to a&lt;br&gt;
given directory, starting from the root directory. In the case of&lt;br&gt;
&lt;code&gt;home&lt;/code&gt;, its absolute path is &lt;code&gt;/home&lt;/code&gt;, as it is directly located under&lt;br&gt;
&lt;code&gt;/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Any path starting with &lt;code&gt;/&lt;/code&gt; is an absolute path.&lt;/p&gt;

&lt;p&gt;We can then use that path to inspect the content of the &lt;code&gt;home&lt;/code&gt; directory&lt;br&gt;
with the &lt;code&gt;ls&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; /home
br
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The absolute path of &lt;code&gt;br&lt;/code&gt; is &lt;code&gt;/home/br&lt;/code&gt;. Each directory is separated&lt;br&gt;
from its parent by a &lt;code&gt;/&lt;/code&gt;. This is why the root directory is called &lt;code&gt;/&lt;/code&gt;:&lt;br&gt;
it is the only directory without a parent.&lt;/p&gt;

&lt;p&gt;Any path that does not start with &lt;code&gt;/&lt;/code&gt; will be a &lt;em&gt;&lt;span class="gls"&gt;relative path&lt;/span&gt;&lt;/em&gt;, meaning that it will be relative to&lt;br&gt;
the current directory. When we executed the &lt;code&gt;ls bin&lt;/code&gt; command, &lt;code&gt;bin&lt;/code&gt; was&lt;br&gt;
actually a relative path. Indeed, we executed that command while we were&lt;br&gt;
located in &lt;code&gt;/home/br&lt;/code&gt;, meaning that the absolute path of &lt;code&gt;bin&lt;/code&gt; was&lt;br&gt;
&lt;code&gt;/home/br/bin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Each folder on disk has a link to itself called &lt;code&gt;.&lt;/code&gt;, and and link to its&lt;br&gt;
parent folder called &lt;code&gt;..&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tczHfnMO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/dotpaths.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tczHfnMO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/dotpaths.png" alt="The `.` link points to the folder itself and the `..` link points to&amp;lt;br&amp;gt;
the folder’s parent"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;The &lt;code&gt;.&lt;/code&gt; link points to the folder itself and the &lt;code&gt;..&lt;/code&gt; link points to the folder’s parent&lt;/span&gt;.&lt;/p&gt;

&lt;p&gt;We can use these &lt;code&gt;.&lt;/code&gt; and &lt;code&gt;..&lt;/code&gt; links when constructing relative paths.&lt;br&gt;
For example, were you current located in &lt;code&gt;/home/br&lt;/code&gt;, you could refer to&lt;br&gt;
the &lt;code&gt;Android&lt;/code&gt; folder as &lt;code&gt;./Android&lt;/code&gt;, meaning “the &lt;code&gt;Android&lt;/code&gt; folder&lt;br&gt;
located under &lt;code&gt;.&lt;/code&gt; (the current directory)”.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; ./Android
Sdk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Were you located under &lt;code&gt;/home/br/Android&lt;/code&gt;, you could also refer as&lt;br&gt;
&lt;code&gt;/home/br/Downloads&lt;/code&gt; as &lt;code&gt;../Downloads&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--64DSzmbt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/dotdot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--64DSzmbt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/dotdot.png" alt="Following `Android`’s `..` link takes you back to the `home` directory"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;Following &lt;code&gt;Android&lt;/code&gt;’s &lt;code&gt;..&lt;/code&gt; link takes you back to the &lt;code&gt;home&lt;/code&gt; director&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ls -a&lt;/code&gt; allows you to see &lt;em&gt;hidden files&lt;/em&gt;, a.k.a all files starting with&lt;br&gt;
a dot. We can indeed see the &lt;code&gt;.&lt;/code&gt; and &lt;code&gt;..&lt;/code&gt; links!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt;  ..  Sdk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;mkdir&lt;/code&gt;: creating directories
&lt;/h3&gt;

&lt;p&gt;In order to make sure that we don’t mess with your personal files when&lt;br&gt;
testing out the commands from this chapter, we will start by creating a&lt;br&gt;
new directory to experiment in, called &lt;code&gt;experiments&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can create a new directory using the &lt;code&gt;mkdir&lt;/code&gt; command, which stands&lt;br&gt;
for &lt;em&gt;make directories&lt;/em&gt;. By executing the command &lt;code&gt;mkdir experiments&lt;/code&gt;,&lt;br&gt;
you will create the &lt;code&gt;experiments&lt;/code&gt; directory in your current directory.&lt;br&gt;
Let’s test this out.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls
&lt;/span&gt;Android                code       Downloads              Music
AndroidStudioProjects  Desktop    Dropbox                Pictures
bin                    Documents  Firefox_wallpaper.png  Videos

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;experiments
&lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Notice that the &lt;code&gt;mkdir&lt;/code&gt; command did not display anything. It might feel&lt;br&gt;
unusual at first, but this is the philosophy of these commands: only&lt;br&gt;
display something if something went bad. In other terms, no news if good&lt;br&gt;
news.&lt;/p&gt;

&lt;p&gt;We can now check that the directory has been created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls
&lt;/span&gt;Android          bin   Desktop  Downloads  experiments      Music     Videos
AndroidStudioProjects  code  Documents  Dropbox    Firefox_wallpaper.png  Pictures
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can also see that directory by opening our file explorer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hBTRj8vy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/new-dir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hBTRj8vy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/new-dir.png" alt="The directory we have just created in the terminal can be seen in our file explorer. The terminal displays the information as text, and the file explorer displays it in a graphical form."&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;The directory we have just created in the terminal can be seen in our file explorer. The terminal displays the information as text, and the file explorer displays it in a graphical form.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;mkdir&lt;/code&gt; on a pre-existing command causes it to fail and display&lt;br&gt;
an error message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;experiments
&lt;span class="nb"&gt;mkdir&lt;/span&gt;: experiments: File exists
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What if we wanted to create a directory in &lt;code&gt;experiments&lt;/code&gt; called &lt;code&gt;art&lt;/code&gt;,&lt;br&gt;
and another directory called &lt;code&gt;paintings&lt;/code&gt; itself located into &lt;code&gt;art&lt;/code&gt;?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;experiments/art/paintings
&lt;span class="nb"&gt;mkdir&lt;/span&gt;: experiments/art: No such file or directory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Something clearly went wrong here. &lt;code&gt;mkdir&lt;/code&gt; is complaining that it cannot&lt;br&gt;
create &lt;code&gt;paintings&lt;/code&gt; within &lt;code&gt;experiments/art&lt;/code&gt; as it does not exist. We&lt;br&gt;
could create &lt;code&gt;art&lt;/code&gt; and then &lt;code&gt;paintings&lt;/code&gt;, in two separate commands, but&lt;br&gt;
fortunately, &lt;code&gt;mkdir&lt;/code&gt; provides us with a &lt;code&gt;-p&lt;/code&gt; option that causes &lt;code&gt;mkdir&lt;/code&gt;&lt;br&gt;
to succeed even if directories already exist, and that will create each&lt;br&gt;
parent directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;-p&lt;/span&gt;, &lt;span class="nt"&gt;--parents&lt;/span&gt;: no error &lt;span class="k"&gt;if &lt;/span&gt;existing, make parent directories as needed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This looks like exactly what we need in that case! Let’s see if it works&lt;br&gt;
as expected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; experiments/art/paintings
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;experiments
art
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;experiments/art
paintings
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;experiments/art/paintings
&lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;cp&lt;/code&gt;, &lt;code&gt;mv&lt;/code&gt;: moving files around
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;cp&lt;/code&gt; (standing for &lt;code&gt;copy&lt;/code&gt;) allows you to copy a file or a directory to&lt;br&gt;
another location.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cp &lt;/span&gt;Documents/readme experiments/art
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;experiments/art
paintings   readme
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;Documents
readme
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can also move the file from a location to another by using &lt;code&gt;mv&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mv &lt;/span&gt;experiments/art/readme experiments
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;experiments
art   readme
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;experiments/art
paintings
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That does not seem to work on directories however.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cp &lt;/span&gt;experiments/art experiments/art-copy
&lt;span class="nb"&gt;cp&lt;/span&gt;: experiments/art is a directory &lt;span class="o"&gt;(&lt;/span&gt;not copied&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By default, &lt;code&gt;cp&lt;/code&gt; only works on files, and not on directories. We need to&lt;br&gt;
use the &lt;code&gt;-r&lt;/code&gt; option to tell &lt;code&gt;cp&lt;/code&gt; to recursively copy &lt;code&gt;experiments/art&lt;/code&gt;&lt;br&gt;
to &lt;code&gt;experiments/art-copy&lt;/code&gt;, meaning &lt;code&gt;cp&lt;/code&gt; will copy the directory and&lt;br&gt;
every file and directories it contains.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; experiments/art experiments/art-copy
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;experiments
art-copy art  readme
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;experiments/art
paintings
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;experiments/art-copy
paintings
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, you can use &lt;code&gt;mv&lt;/code&gt; to rename a file or a directory. It might&lt;br&gt;
sound surprising that there is not &lt;code&gt;rn&lt;/code&gt; or &lt;code&gt;rename&lt;/code&gt; command, but&lt;br&gt;
renaming a file is actually just moving it to another location in the&lt;br&gt;
same directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mv &lt;/span&gt;experiments/readme experiments/README
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;experiments
README    art-copy art
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;rm&lt;/code&gt;: removing files and directories
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;rm&lt;/code&gt; copy allows you to delete files and directories.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be careful with &lt;code&gt;rm&lt;/code&gt;&lt;/strong&gt;, when a file is deleted, it is not moved to the&lt;br&gt;
trash, it is gone.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;rm &lt;/span&gt;experiments/README
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;experiments
art-copy art
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;rm&lt;/code&gt; behaves like &lt;code&gt;cp&lt;/code&gt;: it only allows you to remove directories by&lt;br&gt;
using the &lt;code&gt;-r&lt;/code&gt; option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;rm &lt;/span&gt;experiments/art
&lt;span class="nb"&gt;rm&lt;/span&gt;: experiments/art: is a directory
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; experiments/art
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;experiments
art-copy
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; experiments/art-copy
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;experiments
&lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;ln&lt;/code&gt;: creating links
&lt;/h3&gt;

&lt;p&gt;Have you ever created a shortcut to a file on your desktop? Behind the&lt;br&gt;
scenes, this works using a &lt;em&gt;symbolic link&lt;/em&gt;. A link points to the&lt;br&gt;
original file, and allows you to access that file from multiple places,&lt;br&gt;
without actually having to store multiple copies on disk.&lt;/p&gt;

&lt;p&gt;We can create such a link by using the &lt;code&gt;ln -s&lt;/code&gt; command (&lt;code&gt;-s&lt;/code&gt; stands for&lt;br&gt;
&lt;em&gt;symbolic&lt;/em&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/br
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; Documents/readme Desktop/my-readme
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Using the &lt;code&gt;-l&lt;/code&gt; option of &lt;code&gt;ls&lt;/code&gt;, we can see where a link points to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; Desktop
total 0
lrwxr-xr-x  1 br  br  21 Jan 17 16:48 my-readme -&amp;gt; /home/br/Documents/readme
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;My personal mnemonic to remember the order of arguments is by&lt;br&gt;
remembering &lt;em&gt;s for source&lt;/em&gt;: the source file goes after the &lt;code&gt;-s&lt;/code&gt; option.&lt;br&gt;
&lt;code&gt;ln -s &amp;lt;source&amp;gt;&lt;/code&gt;&lt;/p&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;tree&lt;/code&gt;: visualizing files and subfolders
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;tree&lt;/code&gt; displays the content of the current directory (or argument&lt;br&gt;
directory) and its subfolders in a tree-like representation. It is very&lt;br&gt;
useful to have a quick look at the current content of a directory,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree experiments
experiments
|__ art
    |__ paintings

2 directories, 0 files
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;tree&lt;/code&gt; might not be installed by default, depending on your system. We&lt;br&gt;
mention it here as we will re-use it throughout the chapters.&lt;/p&gt;

&lt;p&gt;&lt;a id="learning-new-options"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning new options
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Getting help
&lt;/h3&gt;

&lt;p&gt;If you are wondering how you will be able to remember all these options,&lt;br&gt;
don’t worry. Nobody expects you to know all of the options of all the&lt;br&gt;
commands by heart. You can rely on the commands’ documentation instead&lt;br&gt;
of having to memorize them all.&lt;/p&gt;

&lt;p&gt;Most of the commands out there take a &lt;code&gt;-h&lt;/code&gt; (or &lt;code&gt;--help&lt;/code&gt;) option that&lt;br&gt;
will display the list of options the command itself can take, and what&lt;br&gt;
they do.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;--help&lt;/span&gt;
Usage: &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;OPTION]... &lt;span class="o"&gt;[&lt;/span&gt;FILE]...
List information about the FILEs &lt;span class="o"&gt;(&lt;/span&gt;the current directory by default&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Sort entries alphabetically &lt;span class="k"&gt;if &lt;/span&gt;none of &lt;span class="nt"&gt;-cftuvSUX&lt;/span&gt; nor &lt;span class="nt"&gt;--sort&lt;/span&gt; is specified.

Mandatory arguments to long options are mandatory &lt;span class="k"&gt;for &lt;/span&gt;short options too.
  &lt;span class="nt"&gt;-a&lt;/span&gt;, &lt;span class="nt"&gt;--all&lt;/span&gt;                  &lt;span class="k"&gt;do &lt;/span&gt;not ignore entries starting with &lt;span class="nb"&gt;.&lt;/span&gt;
  &lt;span class="nt"&gt;-A&lt;/span&gt;, &lt;span class="nt"&gt;--almost-all&lt;/span&gt;           &lt;span class="k"&gt;do &lt;/span&gt;not list implied &lt;span class="nb"&gt;.&lt;/span&gt; and ..
      &lt;span class="nt"&gt;--author&lt;/span&gt;               with &lt;span class="nt"&gt;-l&lt;/span&gt;, print the author of each file
  &lt;span class="nt"&gt;-b&lt;/span&gt;, &lt;span class="nt"&gt;--escape&lt;/span&gt;               print C-style escapes &lt;span class="k"&gt;for &lt;/span&gt;nongraphic characters
      &lt;span class="nt"&gt;--block-size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;SIZE      with &lt;span class="nt"&gt;-l&lt;/span&gt;, scale sizes by SIZE when printing them&lt;span class="p"&gt;;&lt;/span&gt;
                               e.g., &lt;span class="s1"&gt;'--block-size=M'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; see SIZE format below
  &lt;span class="nt"&gt;-B&lt;/span&gt;, &lt;span class="nt"&gt;--ignore-backups&lt;/span&gt;       &lt;span class="k"&gt;do &lt;/span&gt;not list implied entries ending with ~
  &lt;span class="nt"&gt;-c&lt;/span&gt;                         with &lt;span class="nt"&gt;-lt&lt;/span&gt;: &lt;span class="nb"&gt;sort &lt;/span&gt;by, and show, ctime &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;time &lt;/span&gt;of last
                               modification of file status information&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                               with &lt;span class="nt"&gt;-l&lt;/span&gt;: show ctime and &lt;span class="nb"&gt;sort &lt;/span&gt;by name&lt;span class="p"&gt;;&lt;/span&gt;
                               otherwise: &lt;span class="nb"&gt;sort &lt;/span&gt;by ctime, newest first
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;cut &lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;brevity]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It’s interesting to note that some options accept both short and long&lt;br&gt;
forms, like &lt;code&gt;-a/--all&lt;/code&gt;, while some others only accept a short form&lt;br&gt;
(&lt;code&gt;-c&lt;/code&gt;) or a long form (&lt;code&gt;--author&lt;/code&gt;). There’s no real rule there, only&lt;br&gt;
conventions. A command might not even accept a &lt;code&gt;--help&lt;/code&gt; option, but most&lt;br&gt;
if not all the common ones do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &lt;code&gt;-h&lt;/code&gt; is not always the short option for &lt;code&gt;--help&lt;/code&gt;. Indeed, we’ve seen&lt;br&gt;
that &lt;code&gt;ls --help&lt;/code&gt; prints an overview of all available commands, whereas&lt;br&gt;
&lt;code&gt;ls -h&lt;/code&gt; displays units in a human-readable format!&lt;/p&gt;
&lt;h3&gt;
  
  
  Reading the manual
&lt;/h3&gt;

&lt;p&gt;Sometimes, there’s no &lt;code&gt;--help&lt;/code&gt; option available, or its output isn’t&lt;br&gt;
clear or verbose enough for your taste, or the output is too long to&lt;br&gt;
navigate easily. It’s often a good idea to read the command’s &lt;em&gt;&lt;code&gt;man&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
page (&lt;em&gt;man&lt;/em&gt; stands for &lt;em&gt;manual&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Let’s give it a go, by typing the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;man &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b4YSGAK4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/man-ls.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b4YSGAK4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/man-ls.png" alt="`man ls` displays the manual of the `ls` command: everything you need to know about what `ls` can be used for."&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;&lt;code&gt;man ls&lt;/code&gt; displays the manual of the &lt;code&gt;ls&lt;/code&gt; command: everything you need to know about what &lt;code&gt;ls&lt;/code&gt; can be used for.&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Reading the synopsis
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;man&lt;/code&gt; provides you with a &lt;em&gt;synopsis&lt;/em&gt;, describing a specific usage of the&lt;br&gt;
command on each line, along with the associated options and arguments.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ls&lt;/code&gt; synopsis is&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SYNOPSIS
       ls [OPTION]... [FILE]...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;[OPTION]&lt;/code&gt; and &lt;code&gt;[FILE]&lt;/code&gt; means that both options and files are&lt;br&gt;
&lt;em&gt;optional&lt;/em&gt;. As we’ve seen at the beginning of this chapter, just running&lt;br&gt;
&lt;code&gt;ls&lt;/code&gt; on its own prints the content of the current working directory.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;...&lt;/code&gt; following &lt;code&gt;[OPTION]&lt;/code&gt; and &lt;code&gt;[FILE]&lt;/code&gt; means that several options&lt;br&gt;
and several files arguments can be passed as arguments to &lt;code&gt;ls&lt;/code&gt;, as&lt;br&gt;
illustrated by the following example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-sh&lt;/span&gt; Android bin
Android:
total 4.0K
4.0K Sdk

bin:
total 52M
4.7M bat            4.0K fix-vlc-size  3.2M lf           44M terraform  4.0K vpnconnect
4.0K clean-desktop  4.0K itresize      4.0K nightlight  4.0K tv-mode
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we look at the &lt;code&gt;mkdir&lt;/code&gt; synopsis, we see that options are, well,&lt;br&gt;
optional, but we must provide it with one or more directories to create,&lt;br&gt;
because &lt;code&gt;DIRECTORY&lt;/code&gt; is not between square brackets.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SYNOPSIS
       mkdir [OPTION]... DIRECTORY...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;DESCRIPTION&lt;/code&gt; section will list all possible options (short and long&lt;br&gt;
forms), along with their effect.&lt;/p&gt;
&lt;h4&gt;
  
  
  Navigating the manual
&lt;/h4&gt;

&lt;p&gt;When you run &lt;code&gt;man&lt;/code&gt;, the manual of the command will be displayed in a&lt;br&gt;
&lt;em&gt;&lt;span class="gls"&gt; pager&lt;/span&gt;&lt;/em&gt;, a piece of software that&lt;br&gt;
helps the user get the output one page at a time. One of the most common&lt;br&gt;
pager commands is &lt;code&gt;less&lt;/code&gt; (which is incidentally the more featureful&lt;br&gt;
successor of &lt;code&gt;more&lt;/code&gt;, because &lt;em&gt;less is more&lt;/em&gt;). Being dropped into a pager&lt;br&gt;
for the first time is confusing, as you might not know how to to&lt;br&gt;
navigate.&lt;/p&gt;

&lt;p&gt;The most useful commands you can type within &lt;code&gt;less&lt;/code&gt; are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;h&lt;/code&gt;: display the &lt;code&gt;less&lt;/code&gt; help&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;q&lt;/code&gt;: exit &lt;code&gt;less&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;/pattern&lt;/code&gt;: look for the input text located after the cursor’s
current position&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;n&lt;/code&gt;: go to next pattern occurrence&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;?pattern&lt;/code&gt;: look for the input text located before the cursor’s
current position&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;N&lt;/code&gt; go to the pattern previous occurrence&lt;/li&gt;
&lt;li&gt;  up or down arrow to navigate up or down a line&lt;/li&gt;
&lt;li&gt;  PageUp and PageDown keys to navigate up or down a page&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;g&lt;/code&gt; go to the beginning of the file&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;G&lt;/code&gt; go to the end of the file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if you’re not sure what the &lt;code&gt;-s&lt;/code&gt; &lt;code&gt;ls&lt;/code&gt; option is doing, you&lt;br&gt;
can type &lt;code&gt;man ls&lt;/code&gt; and then &lt;code&gt;/-s&lt;/code&gt; when you are in &lt;code&gt;less&lt;/code&gt;. Type &lt;code&gt;n&lt;/code&gt; until&lt;br&gt;
you find the documentation for &lt;code&gt;-s, --size&lt;/code&gt; (or &lt;code&gt;N&lt;/code&gt; to go back if you&lt;br&gt;
went too far). Once you’re done, you can exit &lt;code&gt;less&lt;/code&gt; by typing &lt;code&gt;q&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;While &lt;code&gt;man&lt;/code&gt; uses &lt;code&gt;less&lt;/code&gt; under the hood to help you read documentation,&lt;br&gt;
you can simply use &lt;code&gt;less&lt;/code&gt; to page through any file your disk. For&lt;br&gt;
example, I can use this command on my computer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;less Documents/readme
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vHK_l4OO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/less-readme.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vHK_l4OO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/less-readme.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can look into the &lt;code&gt;less&lt;/code&gt; help itself, by typing &lt;code&gt;h&lt;/code&gt; when reading a&lt;br&gt;
man page, by typing &lt;code&gt;less --help&lt;/code&gt; in a terminal, or even &lt;code&gt;man less&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;Exactly like &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;man&lt;/code&gt; itself is a command, and as most of the&lt;br&gt;
commands, it has a manual! You can read more about &lt;code&gt;man&lt;/code&gt; itself by&lt;br&gt;
typing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;man man
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PnVtaDDt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/man-man.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PnVtaDDt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/man-man.png" alt="Low and behold, the manual’s manual."&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;Low and behold, the manual’s manual.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="command-inputoutput-streams"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Command Input/Output streams
&lt;/h2&gt;

&lt;p&gt;Before we can fully explain what makes the shell so powerful, we need to&lt;br&gt;
explain what is an &lt;em&gt;&lt;span class="gls"&gt;Input Output&lt;br&gt;
stream&lt;/span&gt;&lt;/em&gt;. Every time we run a command, the shell executes a&lt;br&gt;
&lt;em&gt;process&lt;/em&gt;, which will then be in charge of running the command, and&lt;br&gt;
communicating its output back to the terminal. Input/Output streams are&lt;br&gt;
the way the shell sends input to a process and dispatches output from&lt;br&gt;
it.&lt;/p&gt;

&lt;p&gt;Each process has 3 streams by default:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;stdin&lt;/code&gt; (or &lt;em&gt;standard input&lt;/em&gt;): provides input to the command&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;stdout&lt;/code&gt; (or &lt;em&gt;standard output&lt;/em&gt;): displays the command’s output&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;stderr&lt;/code&gt; (or &lt;em&gt;standard error&lt;/em&gt;): displays the command’s error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these streams have an associated &lt;em&gt;&lt;span class="gls"&gt;file descriptor&lt;/span&gt;&lt;/em&gt;, a number used by the shell to&lt;br&gt;
reference that stream. &lt;code&gt;stdin&lt;/code&gt; has the file descriptor 0, &lt;code&gt;stdout&lt;/code&gt; has&lt;br&gt;
1, and &lt;code&gt;stderr&lt;/code&gt; has 2.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bUnR71tM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/process-stream.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bUnR71tM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/process-stream.png" alt="stdin (file descriptor 0) is the process input stream, stdout (file descriptor 1) is the process output stream and stderr (file descriptor 2) is the process error stream"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;&lt;code&gt;stdin&lt;/code&gt; (file descriptor 0) is the process input stream, &lt;code&gt;stdout&lt;/code&gt; (file descriptor 1) is the process output stream and &lt;code&gt;stderr&lt;/code&gt; (file descriptor 2) is the process error stream.&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Redirecting output to a file
&lt;/h3&gt;

&lt;p&gt;It can be convenient to “save” the output of a command to a file, to&lt;br&gt;
further process it at a later time, or to send it to someone else. You&lt;br&gt;
can use the &lt;code&gt;&amp;gt;&lt;/code&gt; operator to redirect the &lt;code&gt;stdout&lt;/code&gt; of a command to a&lt;br&gt;
file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; /home/br &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ls-home.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can then display the content of the &lt;code&gt;ls-home.txt&lt;/code&gt; file using the&lt;br&gt;
&lt;code&gt;cat&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;ls-home.txt
Android                code       Downloads              Music
AndroidStudioProjects  Desktop    Dropbox                Pictures
bin                    Documents  Firefox_wallpaper.png  Videos
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If the file doesn’t already exist, it will be created by the shell at&lt;br&gt;
the moment of the redirection. If the file however does exist at&lt;br&gt;
redirection time, it will be overwritten, meaning that anything that&lt;br&gt;
file used to contain will be replaced by the output of the redirected&lt;br&gt;
command.&lt;/p&gt;

&lt;p&gt;In that example, we use the &lt;code&gt;echo&lt;/code&gt; command, that simply sends the&lt;br&gt;
argument text to its &lt;code&gt;stdout&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;ls-home.txt
Android                code       Downloads              Music
AndroidStudioProjects  Desktop    Dropbox                Pictures
bin
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello world!"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ls-home.txt
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;ls-home.txt
Hello world!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you want to append the output of a command to a file without&lt;br&gt;
overwriting its content, you can use the &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; operator instead of &lt;code&gt;&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;echoes
&lt;span class="nb"&gt;cat&lt;/span&gt;: echoes: No such file or directory
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hey, I just met you, and this is crazy"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; echoes
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"so here's my echo, so cat it maybe"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; echoes
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;echoes
Hey, I just met you, and this is crazy
so here&lt;span class="s1"&gt;'s my echo, so cat it maybe
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Redirecting a file to a command’s input
&lt;/h3&gt;

&lt;p&gt;The same way you can redirect a command’s &lt;code&gt;stdout&lt;/code&gt; to a file, you can&lt;br&gt;
redirect a file to a command’s &lt;code&gt;sdtin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In that example, we’ll redirect the content of the &lt;code&gt;echoes&lt;/code&gt; file to the&lt;br&gt;
input of the &lt;code&gt;wc -l&lt;/code&gt; command, counting the number of lines of its input&lt;br&gt;
stream or the file(s) passed by argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;echoes
Hey, I just met you, and this is crazy
so here&lt;span class="s1"&gt;'s my echo, so cat it maybe
$ wc -l &amp;lt; echoes
2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can of course combined the &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; operators in a single&lt;br&gt;
command. In the following example, we will redirect the content of the&lt;br&gt;
&lt;code&gt;echoes&lt;/code&gt; file to the &lt;code&gt;wc -l&lt;/code&gt; command, and redirect the output of that&lt;br&gt;
command to the &lt;code&gt;echoes-lines&lt;/code&gt; files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; &amp;lt; echoes &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; echoes-lines
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; &amp;lt; echoes &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; echoes-lines
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;echoes-lines
2
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;echoes
Hey, I just met you, and this is crazy
so here&lt;span class="s1"&gt;'s my echo, so cat it maybe
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Redirecting multiple lines to a command’s input
&lt;/h3&gt;

&lt;p&gt;You might find yourself in a situation where you want to pass multiple&lt;br&gt;
lines of input to a command, and the &lt;code&gt;&amp;lt;&lt;/code&gt; operator fails you in that&lt;br&gt;
case, as it only deals with files. Luckily, your shell provides you with&lt;br&gt;
the &lt;em&gt;heredoc&lt;/em&gt; (here document) &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; operator to accomplish this.&lt;/p&gt;

&lt;p&gt;A heredoc redirection has the following syntax:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;command &amp;lt;&amp;lt; DELIMITER
a multi-line
string
DELIMITER
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;DELIMITER&lt;/code&gt; can be any string of your choosing, although &lt;code&gt;EOF&lt;/code&gt; (“end&lt;br&gt;
of file”) is pretty commonly used.&lt;/p&gt;

&lt;p&gt;Let’s consider the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
My username is br
I'm living at /home/br
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This command will output the following block of text:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;My username is br
I'm living at /home/br
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can redirect that block into a file by combining both the &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; and&lt;br&gt;
&lt;code&gt;&amp;gt;&lt;/code&gt; operators.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; aboutme &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
My username is br
I'm living at /home/br
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;aboutme
My username is br
I&lt;span class="s1"&gt;'m living at /home/br
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Redirecting &lt;code&gt;stderr&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Let’s consider the following example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; notthere &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; notthere-with-line-numbers
&lt;span class="nb"&gt;cat&lt;/span&gt;: notthere: No such file or directory
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;notthere-with-line-numbers
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;How come the &lt;code&gt;notthere-with-line-numbers&lt;/code&gt; file is empty even after we&lt;br&gt;
redirected the &lt;code&gt;cat -n notthere&lt;/code&gt; command’s output to it? The reason for&lt;br&gt;
that is, we didn’t really redirect the command’s output to that file, we&lt;br&gt;
redirected the command’s &lt;code&gt;stdout&lt;/code&gt;. As the file &lt;code&gt;notthere&lt;/code&gt; does not&lt;br&gt;
exist, the &lt;code&gt;cat&lt;/code&gt; command fails, and displays an error message on it’s&lt;br&gt;
&lt;code&gt;stderr&lt;/code&gt; stream, which wasn’t redirected.&lt;/p&gt;

&lt;p&gt;You can redirect a process stream by using its file descriptor.&lt;br&gt;
Remember? 0 for &lt;code&gt;stdin&lt;/code&gt;, 1 for &lt;code&gt;stdout&lt;/code&gt; and 2 for &lt;code&gt;stderr&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; notthere  2&amp;gt;errors.txt
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;errors.txt
&lt;span class="nb"&gt;cat&lt;/span&gt;: notthere: No such file or directory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;stderr&lt;/code&gt; redirection can be illustrated by the following diagram.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fDkse2NP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/redirect-stderr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fDkse2NP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/redirect-stderr.png" alt="Any errors displayed by `cat` will be redirected into the `errors.txt` file"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;Any errors displayed by &lt;code&gt;cat&lt;/code&gt; will be redirected into the &lt;code&gt;errors.txt&lt;/code&gt; file&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;You can also redirect the command’s &lt;code&gt;sdterr&lt;/code&gt; to a file, and its &lt;code&gt;stderr&lt;/code&gt;&lt;br&gt;
to another file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; notthere &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;output.txt 2&amp;gt;errors.txt
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;output.txt
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;errors.txt
&lt;span class="nb"&gt;cat&lt;/span&gt;: notthere: No such file or directory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--piFkf5Av--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/redirect-stdout-stderr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--piFkf5Av--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/redirect-stdout-stderr.png" alt="Normal output will be redirected into `output.txt` whereas errors are redirected to into `errors.txt`"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;Normal output will be redirected into &lt;code&gt;output.txt&lt;/code&gt; whereas errors are redirected to into &lt;code&gt;errors.txt&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;It is also possible to redirect the command’s &lt;code&gt;stderr&lt;/code&gt; into its &lt;code&gt;stdout&lt;/code&gt;&lt;br&gt;
using &lt;code&gt;2&amp;gt;&amp;amp;1&lt;/code&gt;. This will effectively merge both streams into a single&lt;br&gt;
one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;notthere &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; output.txt 2&amp;gt;&amp;amp;1
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;output.txt
&lt;span class="nb"&gt;cat&lt;/span&gt;: notthere: No such file or directory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--phy8CmfE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/redirect-stderr-into-stdout.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--phy8CmfE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/redirect-stderr-into-stdout.png" alt="`cat`’s stdout and stderr are merged together into a single stream"&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;&lt;code&gt;cat&lt;/code&gt;’s stdout and stderr are merged together into a single stream&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;The order of redirections has always felt a little bit weird to me.&lt;br&gt;
You’d expect the following syntax to work, as it feels (at least to me)&lt;br&gt;
more logical, by saying “redirect all errors to stdout, and redirect the&lt;br&gt;
whole thing to a file”. It does not work though.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;notthere 2&amp;gt;&amp;amp;1 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; output.txt
&lt;span class="nb"&gt;cat&lt;/span&gt;: notthere: No such file or directory
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;output.txt
&lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a id="composing-commands"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Composing commands
&lt;/h2&gt;

&lt;p&gt;Being able to use a myriad of commands, each one with its own purpose,&lt;br&gt;
is powerful. However, the true power of the shell comes from the fact&lt;br&gt;
that these commands can be &lt;strong&gt;combined&lt;/strong&gt;. This is where the terminal&lt;br&gt;
takes a radical shift from the philosophy of graphical applications.&lt;br&gt;
Where a &lt;span class="gls"&gt;GUI&lt;/span&gt; allows you to use a set&lt;br&gt;
of predefined tools, the shell allows you to assemble commands into your&lt;br&gt;
own specialized tools.&lt;/p&gt;

&lt;p&gt;This is done via the &lt;em&gt;&lt;span class="gls"&gt;pipe&lt;/span&gt;&lt;/em&gt;: &lt;code&gt;|&lt;/code&gt;,&lt;br&gt;
allowing the redirection of a command’s output stream to another&lt;br&gt;
command’s input stream.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;command1 | command2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;A pipe simply works by connecting the &lt;code&gt;stdout&lt;/code&gt; stream of a command to&lt;br&gt;
the &lt;code&gt;stdin&lt;/code&gt; stream of the next command. Simply said, the output of a&lt;br&gt;
command becomes the input of the next.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2VNhLPsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/process-pipe-stream.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2VNhLPsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/process-pipe-stream.png" alt="`ls` is *piped* into `wc` by redirecting its output into `wc`’s input. A pipe allows to compose and assemble commands into pipelines, which makes the terminal so powerful."&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;&lt;code&gt;ls&lt;/code&gt; is &lt;em&gt;piped&lt;/em&gt; into &lt;code&gt;wc&lt;/code&gt; by redirecting its output into &lt;code&gt;wc&lt;/code&gt;’s input. A pipe allows to compose and assemble commands into pipelines, which makes the terminal so powerful.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;You can of course chain as many commands as possible and create command&lt;br&gt;
pipelines.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;command1 | command2 | command3 | ... | commandN
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When you execute&lt;code&gt;command1 | command2&lt;/code&gt;, your shell starts &lt;em&gt;all&lt;/em&gt; commands&lt;br&gt;
at the same time, and a command’s output is streamed into the next one&lt;br&gt;
as the commands run.&lt;/p&gt;

&lt;p&gt;For example, let’s imagine I’d like to count the number of files in my&lt;br&gt;
&lt;code&gt;Downloads&lt;/code&gt; folder. To that effect, I can combine &lt;code&gt;ls&lt;/code&gt; and the &lt;code&gt;wc&lt;/code&gt; (for&lt;br&gt;
&lt;em&gt;word count&lt;/em&gt;) commands. &lt;code&gt;wc&lt;/code&gt;, when used with the &lt;code&gt;-l&lt;/code&gt; options, allows to&lt;br&gt;
count the number of lines in its input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt; ~/Downloads | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
34
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, let’s say I only want to count the number of pdf files in my&lt;br&gt;
&lt;code&gt;Downloads&lt;/code&gt; folder, not just all of them. No problem, &lt;code&gt;grep&lt;/code&gt; to the&lt;br&gt;
rescue! &lt;code&gt;grep&lt;/code&gt; allows to filer its input on a given pattern (more on&lt;br&gt;
&lt;code&gt;grep&lt;/code&gt; in the next chapter). By using &lt;code&gt;grep pdf&lt;/code&gt;, we filter the output&lt;br&gt;
of &lt;code&gt;ls -1&lt;/code&gt; to only the filenames containing “pdf”, and then count how&lt;br&gt;
many filenames were filtered using &lt;code&gt;wc -l&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt; ~/Downloads | &lt;span class="nb"&gt;grep &lt;/span&gt;pdf | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
22
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Going further: redirecting output to both the console and a file
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;tee&lt;/code&gt; command allows you to write a command’s &lt;code&gt;stdout&lt;/code&gt; to a file&lt;br&gt;
while still displaying it into the console. This can be very useful if&lt;br&gt;
you want to store the output of a command in a file, but still be able&lt;br&gt;
to see what it’s doing in real-time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 2 | &lt;span class="nb"&gt;tee &lt;/span&gt;output.txt
Android
code
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;output.txt
Android
code
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iUB_ogPz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/tee.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iUB_ogPz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.balthazar-rouberol.com/images/terminal/tee.png" alt="`tee` is named after the T-splitter used in plumbing."&gt;&lt;/a&gt;&lt;br&gt;
&lt;span class="imgcaption"&gt;&lt;code&gt;tee&lt;/code&gt; is named after the T-splitter used in plumbing.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="escaping-from-bad-situations"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Escaping from bad situations
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Mistyped command, missing arguments
&lt;/h3&gt;

&lt;p&gt;If you mistype a command, or forget to add arguments, you can find&lt;br&gt;
yourself in a situation where your shell hangs, and nothing happens. For&lt;br&gt;
example, type any of the following commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'hello world
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The first command hangs because it is waiting for input on its &lt;code&gt;stdin&lt;/code&gt;&lt;br&gt;
stream, as no argument file was provided. In the case of the second&lt;br&gt;
command, it is missing a matching single quote. In both cases, you get&lt;br&gt;
can out of this situation by hitting Ctrl - C&lt;br&gt;
which kills the command by sending it a interruption signal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: if your shell is stuck on receiving input (like in the &lt;code&gt;cat&lt;/code&gt; example),&lt;br&gt;
you can also cleanly exit it by hitting Ctrl - D&lt;br&gt;
which will send a special EOF (“end of file”) character, indicating to&lt;br&gt;
the command that its input is now closed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat
&lt;/span&gt;hello
hello
world
world
&lt;span class="c"&gt;# Ctrl-D&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Escaping characters
&lt;/h3&gt;

&lt;p&gt;Imagine for a second that you had a file on disk named &lt;code&gt;my file&lt;/code&gt;, and&lt;br&gt;
you wanted to display its content using &lt;code&gt;cat&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;my file
&lt;span class="nb"&gt;cat&lt;/span&gt;: my: No such file or directory
&lt;span class="nb"&gt;cat&lt;/span&gt;: file: No such file or directory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the previous example, the &lt;code&gt;cat&lt;/code&gt; command was given 2 arguments &lt;code&gt;my&lt;/code&gt;&lt;br&gt;
and &lt;code&gt;file&lt;/code&gt;, none of which corresponded to any existing file. We have 2&lt;br&gt;
solutions to make this work: quoting the file name, or using an &lt;span class="gls"&gt;escape character&lt;/span&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="s1"&gt;'my file'&lt;/span&gt;
That file has spaces &lt;span class="k"&gt;in &lt;/span&gt;it...
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="s2"&gt;"my file"&lt;/span&gt;
That file has spaces &lt;span class="k"&gt;in &lt;/span&gt;it...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By putting quotes around the file name, you are telling your shell that&lt;br&gt;
whatever is between the quotes is a single argument.&lt;/p&gt;

&lt;p&gt;Like previously mentioned, we could also use the backslash escape&lt;br&gt;
character, which indicates that whatever following character doesn’t&lt;br&gt;
have any special meaning.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;my&lt;span class="se"&gt;\ &lt;/span&gt;file
That file has spaces &lt;span class="k"&gt;in &lt;/span&gt;it...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By using &lt;code&gt;\&lt;/code&gt; (a backslash character followed by a space), we indicate to&lt;br&gt;
the shell that the space is simply a space, and should not be&lt;br&gt;
interpreted as a separator between 2 arguments.&lt;/p&gt;

&lt;p&gt;&lt;a id="summary"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In that chapter, we’ve discovered what a terminal is: an application in&lt;br&gt;
which you can type text commands to have them executed by a program&lt;br&gt;
called a shell.&lt;/p&gt;

&lt;p&gt;Facing the terminal can be intimidating at first because you might not&lt;br&gt;
always know what command to type. Learning your way around the terminal&lt;br&gt;
is however part of the journey of becoming a software engineer. Like any&lt;br&gt;
other powerful tool, it can be hard to learn but will also make you&lt;br&gt;
immensely more productive once you get more accustomed to it.&lt;/p&gt;

&lt;p&gt;The fundamental philosophy of working in a terminal is being free to&lt;br&gt;
compose different tools in a way that might not have been initially&lt;br&gt;
foreseen by the tools’ developers, by using pipes and stream&lt;br&gt;
redirections. Instead of using a single tool that was only designed to&lt;br&gt;
perform a finite set of tasks, you are free to assemble a patchwork of&lt;br&gt;
unrelated commands, that can all work together by joining their input&lt;br&gt;
and output streams.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://blog.balthazar-rouberol.com/text-processing-in-the-shell"&gt;next chapter&lt;/a&gt;, we will dig into text processing commands, which&lt;br&gt;
can be immensely powerful when chained together with pipes.&lt;/p&gt;

&lt;p&gt;&lt;a id="going-further"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Going further
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1.1&lt;/strong&gt;: Look into the &lt;code&gt;ls&lt;/code&gt; manual and research what the &lt;code&gt;-a&lt;/code&gt; option is&lt;br&gt;
doing. Run &lt;code&gt;ls -a ~/&lt;/code&gt;. What are the &lt;code&gt;.&lt;/code&gt; and &lt;code&gt;..&lt;/code&gt; directories? What are&lt;br&gt;
the files starting with a &lt;code&gt;.&lt;/code&gt; ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.2&lt;/strong&gt;: Run a command and redirect its output into a file, but display&lt;br&gt;
any errors in the terminal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.3&lt;/strong&gt;: Run a command and redirect its output into a file, and any&lt;br&gt;
errors into a different file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.4&lt;/strong&gt;: Run a command and redirect both its output and errors into the&lt;br&gt;
same file, while also displaying them all on screen at the same time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.5&lt;/strong&gt;: Use a heredoc redirection to create a new file with text in it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.6&lt;/strong&gt;: Given an &lt;code&gt;echoes&lt;/code&gt; file, what is the difference between&lt;br&gt;
&lt;code&gt;wc -l echoes&lt;/code&gt;, &lt;code&gt;cat echoes | wc -l&lt;/code&gt; and &lt;code&gt;wc -l &amp;lt; echoes&lt;/code&gt; ?&lt;/p&gt;




&lt;p&gt;
&lt;em&gt;Essential Tools and Practices for the Aspiring Software Developer&lt;/em&gt; is a self-published book project by Balthazar Rouberol and &lt;a href="https://etnbrd.com"&gt;Etienne Brodu&lt;/a&gt;, ex-roommates, friends and colleagues, aiming at empowering the up and coming generation of developers. We currently are hard at work on it!
&lt;/p&gt;

&lt;p&gt;The book will help you set up a productive development environment and get acquainted with tools and practices that, along with your programming languages of choice, will go a long way in helping you grow as a software developer.
  It will cover subjects such as mastering the terminal, configuring and getting productive in a shell, the basics of code versioning with &lt;code&gt;git&lt;/code&gt;, SQL basics, tools such as &lt;code&gt;Make&lt;/code&gt;, &lt;code&gt;jq&lt;/code&gt; and regular expressions, networking basics as well as software engineering and collaboration best practices.
&lt;/p&gt;

&lt;p&gt;
  If you are interested in the project, we invite you to join the &lt;a href="https://balthazar-rouberol.us4.list-manage.com/subscribe?u=1f6080d496af07a836270ff1d&amp;amp;id=81ebd36adb"&gt;mailing list&lt;/a&gt;!
&lt;/p&gt;

</description>
      <category>bash</category>
      <category>tutorial</category>
      <category>computerscience</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
