Jekyll2024-01-03T22:48:00+00:00https://binaryphile.github.io/feed.xmlbinary.phileMusings, mostly on technology.Happier January 2024 - Jan 42024-01-03T12:00:00+00:002024-01-03T12:00:00+00:00https://binaryphile.github.io/life/2024/01/03/happier-january-04<p>Continuing with this <a href="https://actionforhappiness.org/sites/default/files/calendar_download/pdf/Jan%202024.pdf">printable calendar</a> I found on <a href="https://fosstodon.org">Fosstodon</a>.</p>
<dl>
<dt>Jan 4</dt>
<dd>Write a list of things you feel grateful for and why</dd>
</dl>
<dl>
<dt>Plan</dt>
<dd>No plan needed for this one</dd>
</dl>Continuing with this printable calendar I found on Fosstodon.Happier January 2024 - Jan 32024-01-02T12:01:00+00:002024-01-02T12:01:00+00:00https://binaryphile.github.io/life/2024/01/02/happier-january-03<p>Continuing with this <a href="https://actionforhappiness.org/sites/default/files/calendar_download/pdf/Jan%202024.pdf">printable calendar</a> I found on <a href="https://fosstodon.org">Fosstodon</a>.</p>
<dl>
<dt>Jan 3</dt>
<dd>Do a kind act for someone to brighten their day</dd>
</dl>
<dl>
<dt>Plan</dt>
<dd>I may take this one more extemporaneously. But if not, probably something nice for my wife
in the morning, like making breakfast or getting the kiddo dressed.</dd>
</dl>
<dl>
<dt>How it went</dt>
<dd>Well, I didn't have a lot of opportunities today, but I did make up a bit for
yesterday and watched a "What If..." episode and one of my daughter's favorite Disney
franchises (Zombies 2) with her. We talked about the money she made cat-sitting for our
neighbors and how I reverse-borrowed a tenner from her by putting a twenty in her piggy
bank and taking a ten. So my cheese-out nice thing was to "forgive" the ten I was still
owed, effectively giving her the money. She was grateful, so I suppose it counts.</dd>
</dl>Continuing with this printable calendar I found on Fosstodon.Happier January 2024 - Jan 22024-01-02T12:00:00+00:002024-01-02T12:00:00+00:00https://binaryphile.github.io/life/2024/01/02/happier-january-02<p>Continuing with this <a href="https://actionforhappiness.org/sites/default/files/calendar_download/pdf/Jan%202024.pdf">printable calendar</a> I found on Mastodon.</p>
<p>Jan 2: Make time to do something kind for yourself.</p>
<p>Well, I usually don’t have a problem being kind to myself, so this should be a snap. Let’s
see, what could I do?</p>
<ul>
<li>
<p>food – I’m always getting myself decent food. Too run-of-the-mill.</p>
</li>
<li>
<p>health – I’m stuck lying in bed on my back today, so that’s about as kind as I can be in
this situation</p>
</li>
<li>
<p>family – be with them. I think this is probably the best bet. I’ll have to convince
someone to come in the bedroom and watch TV with me. My daughter won’t take any
convincing. We’ll try that.</p>
</li>
</ul>
<dl>
<dt>How it went</dt>
<dd>I didn't get my daughter to come join me after all, there wasn't enough opportunity
with me being flat on my back. However, I did get up and make myself some tea, so that
will have to do for this one.</dd>
</dl>Continuing with this printable calendar I found on Mastodon.Happier January 2024 - Jan 12024-01-01T12:00:00+00:002024-01-01T12:00:00+00:00https://binaryphile.github.io/life/2024/01/01/happier-january-01<p>I ran across this <a href="https://actionforhappiness.org/sites/default/files/calendar_download/pdf/Jan%202024.pdf">printable calendar</a> on Mastodon and thought it a lovely idea.</p>
<p>For Jan 1, the task is to find 3 things to look forward to this year. Here’s my shot at the
list:</p>
<ul>
<li>
<p>taking my wife on her dream birthday adventure to Diagon Alley at Universal</p>
</li>
<li>
<p>learning how to cook anything from my Mom</p>
</li>
<li>
<p>creating safe community for my daughter online with my <a href="https://portal.mozz.us/gemini/g.lilleygram.com/">gemini social media project</a></p>
</li>
</ul>I ran across this printable calendar on Mastodon and thought it a lovely idea.Using history and subshells2023-06-25T12:00:00+00:002023-06-25T12:00:00+00:00https://binaryphile.github.io/bash/2023/06/25/using-history-and-subshells<p>So, it’s been a while since I blogged. Never mind that, it’s never too
late to write another blog. Let’s just forget that I was supposed to be
in the midst of a series. In order to simplify things, I’m just going
to do the normal blog thing and write some short posts with no greater
arc, just tidbits. And that’s good enough.</p>
<p>In this post, I want to outline a technique I’ve picked up lately, one
which I’ve not run across elsewhere. I’m not claiming origination of
the idea, but I did have to discover it for myself.</p>
<p>TL;DR – put common strings of commands in your history as subshell
commands. While many like to use <code class="language-plaintext highlighter-rouge">&&</code> to stop on errors, I
stylistically prefer using errexit. A subshell allows errexit with
semicolon-separated commands. An example to commit and push all
changes:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">></span> <span class="o">(</span><span class="nb">set</span> <span class="nt">-e</span><span class="p">;</span> <span class="nb">cd</span> <span class="s2">"</span><span class="nv">$PROJECT_ROOT</span><span class="s2">"</span><span class="p">;</span> git add .<span class="p">;</span> git commit <span class="nt">-m</span> <span class="s2">"</span><span class="nv">$msg</span><span class="s2">"</span><span class="p">;</span> git push<span class="o">)</span>
</code></pre></div></div>
<p>- or to sync with main -</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">></span> <span class="o">(</span><span class="nb">set</span> <span class="nt">-e</span><span class="p">;</span> <span class="nb">cd</span> <span class="s2">"</span><span class="nv">$PROJECT_ROOT</span><span class="s2">"</span><span class="p">;</span> git fetch<span class="p">;</span> git rebase origin/main<span class="p">;</span> git push <span class="nt">-f</span><span class="o">)</span>
</code></pre></div></div>
<p>My typical use for this workflow is with <code class="language-plaintext highlighter-rouge">git</code> and <code class="language-plaintext highlighter-rouge">bazel</code> commands.
These tools usually require a short series of operations to do a useful
unit of work. While the operations tend to be few, some may error.
When issuing commands one-at-a-time, interactively, one would typically
stop on an error and attempt a fix.</p>
<p>Bash doesn’t have that behavior by default if you simply run a few
commands on one line (separate them with semicolons like many other
programming languages). Because of this, most people write chained
commands that employ logical AND (<code class="language-plaintext highlighter-rouge">&&</code>) to check the result of the last
command and only run the next if the last command didn’t report failure.</p>
<p>As a bash scripter, I am more used to enabling bash’s builtin safety
features, such as errexit. Errexit tells bash to stop (exit, actually)
whenever a command or function returns an error. (<em>Unless</em>, the result
was part of an expression. Any part except the last in the expression,
actually.)</p>
<p>That means any one-liners I write just need the standard semicolon
separator, not double-ampersand. While it’s not a huge deal, it’s how I
think now and, as well, it does feel nice to use a home-row pinky
instead of a shift-and-reach-index-finger.</p>
<p>A typical workflow for me is to rebase on main prior to making a pull
request (maybe some fixing up as well, but not here for clarity). I
don’t bother keeping a local main checked out, so I just <code class="language-plaintext highlighter-rouge">git fetch</code> to
refresh the remote branch, then rebase on top of that. A final force
push, <code class="language-plaintext highlighter-rouge">git push -f</code>, registers the new head with the remote.</p>
<p>So that reads:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git fetch
git rebase origin/main
git push <span class="nt">-f</span>
</code></pre></div></div>
<p>With errexit, and on a single line, it goes:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">(</span><span class="nb">set</span> <span class="nt">-e</span><span class="p">;</span> git fetch<span class="p">;</span> git rebase origin/main<span class="p">;</span> git push <span class="nt">-f</span><span class="o">)</span>
</code></pre></div></div>
<p>If any step fails, then errexit stops the commands. Notice I’ve put
parentheses around the entire command; this creates a copy of the
current shell, variables and all, prior to running the commands.</p>
<p>Since errexit forces a full exit, the subshell will stop and return
control to the current level of the shell (the one you ran the commands
from).</p>
<p>I’m also partial to subshells whenever using settings aside from
errexit. For example, I almost always turn off globbing by default. To
use a setting such as that for a few commands, a subshell creates a
sandbox that cannot affect your current shell once you’ve returned to
it. So you never need to worry about interfering with your normal
interactive shell settings when you just need some programmatic
strictness for a few commands.</p>
<p>Also notice the handful of variables, such as <code class="language-plaintext highlighter-rouge">$msg</code> and
<code class="language-plaintext highlighter-rouge">$PROJECT_ROOT</code>. <code class="language-plaintext highlighter-rouge">$msg</code> needs to be set per-commit, but <code class="language-plaintext highlighter-rouge">$PROJECT_ROOT</code>
can be set in a direnv file (a handy project tool) so these commands can
automatically adapt to the project at hand.</p>
<p>Finally, you only need to figure out a unique part of the command to
history search for it.</p>
<p>Why put these in history, rather than save them in bashrc or a bin
directory? Because I like to use these commands as second nature, but
when I work with others, they have no idea what I’m doing (that’s not
quite true, I have some other tools that help explain). But being able
to see all of the commands explicitly on the command-line, people have a
chance if they get the time to read any of it, at least. :) So it can
help people follow you as you work.</p>
<p>And when it comes to persistence concerns, I have eternal bash history
to save them, but that’s a different post.</p>So, it’s been a while since I blogged. Never mind that, it’s never too late to write another blog. Let’s just forget that I was supposed to be in the midst of a series. In order to simplify things, I’m just going to do the normal blog thing and write some short posts with no greater arc, just tidbits. And that’s good enough.Bash Environment Variables2022-01-08T12:00:00+00:002022-01-08T12:00:00+00:00https://binaryphile.github.io/bash/2022/01/08/environment-variables<p>If you’re interested, start the series with <a href="/bash/2020/07/02/how-i-bash-a-new-series.html">part 1</a>.</p>
<p>In the <a href="/bash/2020/07/12/customizing-bash.html">last part</a>, we learned about the broad scope of bash
initialization files.</p>
<p>This time let’s pick a specific thing to customize, environment
variables, and see how that’s done.</p>
<p>In particular, let’s use a real-life example. Let’s add a directory to
the PATH environment variable.</p>
<p>If you aren’t familiar with environment variables, the brief explanation
is that they are a method for the shell to pass information (strings, to
be specific) to processes that you tell it to run. An environment
variable is a shell variable with an additional bit of metadata which
tells the operating system to copy the variable into the subprocess of a
command you run.</p>
<p>PATH is the most famous of the environment variables. On a Linux
system, PATH is a colon-separated list of directories. The directories
are locations that are searched one-at-a-time to find an executable
program when you don’t supply that program’s location on the command
line.</p>
<p>Let’s make a directory that will allow us to put programs there when we
want them to appear on the path. By convention, user home directories
usually put them in <code class="language-plaintext highlighter-rouge">~/bin</code> (ok) or <code class="language-plaintext highlighter-rouge">~/.local/bin</code> (better). Let’s make
the directory, then add it to PATH in an initialization file.</p>
<p>As a note, when I run commands on the command line, I’ll use <code class="language-plaintext highlighter-rouge">></code> to
denote the prompt.</p>
<p>Open a command prompt and run <code class="language-plaintext highlighter-rouge">mkdir</code>:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">></span> <span class="nb">mkdir</span> <span class="nt">-p</span> ~/.local/bin
</code></pre></div></div>
<p>The <code class="language-plaintext highlighter-rouge">-p</code> option allows us to make both the <code class="language-plaintext highlighter-rouge">.local</code> as well as the <code class="language-plaintext highlighter-rouge">bin</code>
directory in one go. <code class="language-plaintext highlighter-rouge">~</code> is a special shell character which denotes our
home directory. It’s expanded to our actual home path prior to the
command being executed.</p>
<p>Now let’s add the directory to our path. What we want to do is append
the directory to the existing value of PATH, so we don’t lose the
functionality already given by PATH. Most of the time, you see this
done by expanding the existing PATH in a new PATH assignment:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:<span class="nv">$HOME</span>/.local/bin
</code></pre></div></div>
<p>That command does three things:</p>
<ul>
<li>expands the existing PATH as <code class="language-plaintext highlighter-rouge">$PATH</code></li>
<li>appends <code class="language-plaintext highlighter-rouge">$HOME/.local/bin</code> with a colon <code class="language-plaintext highlighter-rouge">:</code></li>
<li><code class="language-plaintext highlighter-rouge">export</code>s the variable to the environment</li>
</ul>
<p>There’s definitely some redundancy in there that we can simplify out. I
prefer the following more succinct version:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PATH+<span class="o">=</span>:<span class="nv">$HOME</span>/.local/bin
</code></pre></div></div>
<ul>
<li>
<p>I’ve dropped <code class="language-plaintext highlighter-rouge">export</code>. While PATH is not exported to the
environment when bash starts up without any configuration, by
convention, it is exported to the environment in the system’s bash
initialization files. Once exported, an environment variable stays
exported for good, so you don’t have to re-export it. There may be
some esoteric edge case where the system’s files aren’t run while
ours is, but I haven’t encountered it and I like simple until
there’s a demonstrated need for complicated.</p>
</li>
<li>
<p>I’m using the string append operator <code class="language-plaintext highlighter-rouge">+=</code> rather than <code class="language-plaintext highlighter-rouge">=</code>. This
still assigns to the variable, but it adds the right-hand side to
the end of the existing variable value. No need for expansion of
<code class="language-plaintext highlighter-rouge">$PATH</code>. You do need, however, to remember to include the colon
separator yourself. It’s the first character of the right-hand
side, not a part of the <code class="language-plaintext highlighter-rouge">+=</code> operator itself.</p>
</li>
</ul>
<p>Note that for security you typically want to add to the end of your PATH
rather than the beginning, so you don’t accidentally replace a system
command with your own. The directories are searched in order until the
first matching program is found, so earlier directories in PATH
supersede later ones.</p>
<p>You may also have noticed that I didn’t use <code class="language-plaintext highlighter-rouge">~</code> for the home directory
as I do on the command line, instead using <code class="language-plaintext highlighter-rouge">$HOME</code>. As a rule of thumb,
I always use <code class="language-plaintext highlighter-rouge">$HOME</code> in scripts because it is more robust than <code class="language-plaintext highlighter-rouge">~</code>.
Tilde only expands properly if it is at the start of a word, or in an
assignment if it is directly after the <code class="language-plaintext highlighter-rouge">=</code> or a <code class="language-plaintext highlighter-rouge">:</code> separator. That
means that using it in command-line options sometimes fails. <code class="language-plaintext highlighter-rouge">$HOME</code> is
a simple habit which always works in scripts. Interactively on the
command-line, I allow myself to use <code class="language-plaintext highlighter-rouge">~</code> for succinctness.</p>
<p>So we’re almost done here. The last thing to do is determine <em>where</em> to
add this line. There’s generally four options:</p>
<ul>
<li>~/.bash_profile</li>
<li>~/.profile</li>
<li>~/.bash_login</li>
<li>~/.bashrc (not really an option, but you might think so)</li>
</ul>
<p>As we saw in the diagram from the <a href="/bash/2020/07/12/customizing-bash.html">last part</a>, all four of these files
are normally somewhere in the mix of shell startup. It gets confusing
though. Without going into extraordinary detail, the usual place is
.bash_profile.</p>
<p>The reason we don’t want to use .bash_login is that .bash_profile is
preferred and .bash_login won’t be loaded if .bash_profile is present.</p>
<p>.profile and .bash_profile play mostly the same role. .profile is
relied upon by the desktop login system on Ubuntu, so you may already
have that in your directory (other Linuxes may do things differently).
If so, use it. Ubuntu doesn’t open login shells, so .profile is the
general solution in that case. However, if not, I stick with
.bash_profile, so I’ll use that as my reference point for this article
(I’m on MacOS).</p>
<p>You’ll see .bashrc mistakenly recommended as a place to set or modify
environment variables. The problem with .bashrc for environment
variables is that it’s frequently loaded then reloaded. Whenever a new
interactive shell is started, .bashrc is loaded. If it is the first
time that the shell is being loaded, an environment variable set in
.bashrc will be set correctly. However, the process may not end there.
If a command ends up spawning another interactive shell, .bashrc will be
loaded again. The environment variable will already exist from the
ancestor shell, when .bashrc sets/changes it again. If the variable is
being set in .bashrc, any intervening change to the environment variable
will then be overwritten. Alternatively if the variable is being
modified in .bashrc, the change will occur again. This can, for
example, extend PATH with multiple copies of the directory.</p>
<p>For these reasons, .bash_profile is the right place to modify
environment variables like PATH. It is only loaded once by the original
login shell, the ultimate parent. Child shells will only run .bashrc,
not .bash_profile again.</p>
<p>If you already have a .bash_profile, we can add our line to it. The
best location is at the end of the file. That way, if .bash_profile
loads any other files, putting our changes at the end will make sure
that they happen after everything else has made its PATH changes.</p>
<p>The alternative is to add it elsewhere there is a PATH modification
already in the file. That’s fine as well, but add our directory at the
end of the assignment.</p>
<p>Before we make this change, let’s just inspect PATH to make sure we
don’t already have <code class="language-plaintext highlighter-rouge">~/.local/bin</code> there (some systems add it already):</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">></span> <span class="nb">echo</span> <span class="nv">$PATH</span>
</code></pre></div></div>
<p>No? Great. Otherwise, let’s test our modification but back it out
later so as not to duplicate the path.</p>
<p>Open ~/.bash_profile and add the line:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PATH+<span class="o">=</span>:<span class="nv">$HOME</span>/.local/bin
</code></pre></div></div>
<p>Ok, let’s test the change. Unfortunately, there’s one more tricky bit.
If you’re on MacOS, then opening a new terminal window will typically
run a login shell, meaning that it will see the change and you can run
<code class="language-plaintext highlighter-rouge">echo $PATH</code> to verify our change. (that’s good, that’s not the tricky
bit)</p>
<p>On Ubuntu however, the desktop system typically runs ~/.profile.
Opening a new terminal shell will run an interactive shell (not login)
and only .bashrc will be run. In that case, the change will only happen
if you log off and back on. So do that if necessary.</p>
<p>Now, open a new terminal and <code class="language-plaintext highlighter-rouge">echo $PATH</code>. Is our directory there?
Great! Otherwise you’ll need to do some snooping. Start by sourcing
our file explicitly: <code class="language-plaintext highlighter-rouge">source ~/.bash_profile</code> and try again. If that
works but not when you open a new window, then use <code class="language-plaintext highlighter-rouge">shopt login_shell</code>
to see whether you are in a login shell or not. If not, reboot the
machine and try again.</p>
<p>Well, that was quite involved, wasn’t it? It gets easier. At least the
actual change was easy and we won’t need to go over the initialization
file options again.</p>
<p>See the [next part] for application initialization.</p>If you’re interested, start the series with part 1.Customizing Bash2020-07-12T12:00:00+00:002020-07-12T12:00:00+00:00https://binaryphile.github.io/bash/2020/07/12/customizing-bash<p>If you’re interested, start the series with <a href="/bash/2020/07/02/how-i-bash-a-new-series.html">part 1</a>.</p>
<p>In the <a href="/bash/2020/07/06/getting-bash.html">last part</a>, we learned how to get the latest bash, especially if
you’re on a mac.</p>
<p>This time (and for the next few) let’s talk about how I customize bash.</p>
<p>Bash has a lot of settings that don’t have great defaults. For example,
bash keeps track of your command history by default, but it doesn’t hold
very many commands. That doesn’t give you a lot of time to fetch
something from your command history before it’s lost for good. The bash
history is kept in a file in your home directory, and disk space is
cheap, so why not keep thousands of your past commands?</p>
<p>Bash also has the ability for you to create your own commands via
functions and aliases. Functions and aliases are close to the same
thing. While aliases are much more limited, they are easier to write,
so they both have their place. I add a lot of aliases and functions to
make frequently-used commands shorter and complicated commands simpler.
One example is to add a shorter version of the <strong>ls</strong> command with the
options I like: <code class="language-plaintext highlighter-rouge">alias ll='ls -al'</code>. One thing I like to note about
making aliases is that I never replace the basic command itself, i.e. I
never make an alias called <strong>ls</strong>, because I never want to be surprised
by the behavior of the basic command on a system which doesn’t have my
aliases.</p>
<p>Other reasons to customize bash include:</p>
<ul>
<li>
<p>setting useful environment variables</p>
</li>
<li>
<p>adding initialization required by installed packages</p>
</li>
<li>
<p>fun and profit</p>
</li>
</ul>
<p>As I began to tweak bash’s configuration, it became more and more
complex and my initialization files became longer and longer. Not only
that, bash has multiple initialization files which are for different
purposes and are loaded at different times. It can be quite confusing.
If you want to know how much, take a look at this diagram of <a href="https://www.solipsys.co.uk/images/BashStartupFiles1.png">when
the various files are loaded</a>.</p>
<p><img src="https://www.solipsys.co.uk/images/BashStartupFiles1.png" alt="diagram" /></p>
<p>Would you believe that this diagram isn’t even complete?</p>
<p>In any case, there’s quite a bit to absorb. Let’s not try to take
everything in one bite. In particular, let’s gloss over the stuff that
isn’t that important. There are a few things I’ve worried about in my
initialization files:</p>
<ul>
<li>
<p>putting different kinds of settings in separate, well-named files</p>
</li>
<li>
<p>version control and synchronization with git</p>
</li>
<li>
<p>customizing the same set of files for different systems easily</p>
</li>
<li>
<p>using a single file as a starting point, rather than separate
profile and rc files</p>
</li>
<li>
<p>validating that the settings have actually taken effect</p>
</li>
</ul>
<p>That’s enough for an overview. See the <a href="/bash/2022/01/08/environment-variables.html">next part</a> for more details.</p>If you’re interested, start the series with part 1.Getting Bash2020-07-06T22:00:00+00:002020-07-06T22:00:00+00:00https://binaryphile.github.io/bash/2020/07/06/getting-bash<p>If you’re interested, start the series with <a href="/bash/2020/07/02/how-i-bash-a-new-series.html">part 1</a>.</p>
<p>If you’re on linux, you’re in luck. You’ve already got the latest bash
for your release on your system. If you aren’t using it already, you
just need to <a href="https://linux.die.net/man/1/chsh">change your default shell to bash</a>: run
<code class="language-plaintext highlighter-rouge">chsh -s /bin/bash</code>.</p>
<p>If you’re on macos, it’s a bit more involved. The system bash is an
unconscionably old version, and the newest macos releases default to
zsh. You’ll need <a href="https://brew.sh/">homebrew</a> installed first to install the latest bash.
Open a terminal and follow the directions on the homebrew site.</p>
<p>Once homebrew is installed, install bash with <code class="language-plaintext highlighter-rouge">brew install bash</code>.</p>
<p>Then, make bash your default shell. First you’ll need to add it to
<strong>/etc/shells</strong>: run <code class="language-plaintext highlighter-rouge">sudo -e /etc/shells</code>. Add the following line to
the end of the file and save:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/usr/local/bin/bash
</code></pre></div></div>
<p>Next, run <code class="language-plaintext highlighter-rouge">chsh -s /usr/local/bin/bash</code>. Every new terminal window will
use the latest bash. Close your existing window, open a new one and run
<code class="language-plaintext highlighter-rouge">echo $BASH_VERSION</code> to see what version you are on now. It should be a
version of bash 5.</p>
<p>Continue with the <a href="/bash/2020/07/12/customizing-bash.html">next part</a>, customizing bash.</p>If you’re interested, start the series with part 1.I Was Scared Of Bash2020-07-06T12:00:00+00:002020-07-06T12:00:00+00:00https://binaryphile.github.io/bash/2020/07/06/i-was-scared-of-bash<p>If you’re interested, start the series with <a href="/bash/2020/07/02/how-i-bash-a-new-series.html">part 1</a>.</p>
<p>I admit it. I was scared of bash. It seemed so confusing. Whoever
thought <code class="language-plaintext highlighter-rouge">$</code> was a good character for a command prompt? Right from the
get-go, bash felt strange and foreign.</p>
<p>I was used to the familiar <code class="language-plaintext highlighter-rouge">C:\></code>. I was even used to the improved C
shell, <a href="https://www.tcsh.org/">tcsh</a>, although I don’t remember its prompt character (Wikipedia
shows <code class="language-plaintext highlighter-rouge">%</code>, but I think our system had it modified to <code class="language-plaintext highlighter-rouge">></code>).</p>
<p>It just seemed like bash intentionally had been made for an older time,
a relic which preexisted any kind of ergonomics or user experience
concerns. A cursory examination of the home directory initialization
files did little to change that impression. And documentation for bash,
such as the man page, was more dense than Amazonian rainforest.</p>
<p>Nevertheless, I ventured in a bit, writing the <em>de rigeur</em> <code class="language-plaintext highlighter-rouge">ls</code> aliases
and learning the names of <strong>~/.profile</strong>, <strong>~/.bash_profile</strong> and
<strong>~/.bashrc</strong>, not really understanding the difference between them
all.</p>
<p>When I had my own system, I finally decided to learn something about the
shell. But if I was going to invest myself in a shell, I figured I
should learn something that would be more powerful and friendlier than
bash (I learned later that was probably a mistake, at least for me).</p>
<p>I picked up <strong>zsh</strong>, since that seemed to be what all the cool kids were
using. It helped that its primary “killer app” was a decent prompt that
showed useful things like the status of git repo directories. It used
color, and had a plugin system for initialization files and additional
functionality. It seemed like a slam dunk.</p>
<p>However, zsh started to lose its appeal. Yes, there was an easy, cool
prompt. But I started paying attention to those who were saying
oh-my-zsh (the plugin system) was bloated and slow. I also didn’t learn
much new about how to use the shell. zsh was designed to be mostly
bash-compatible, however, that was a double-edged sword. It carried a
lot of the illegibility of bash, while only smoothing off some of the
sharp edges. At least, that’s the impression I had. If I was going to
invest in learning to script in zsh, not only was I giving up
compatibility with most of the systems I work on, I was also going to
have to maintain two bodies of very similar knowledge: what bash and zsh
can do, and now the difference between them as well.</p>
<p>At this point, I started realizing it was going to be difficult not to
learn bash. I hadn’t quite given up yet. I tried fish shell, the
<em>f</em>riendly <em>i</em>nteractive <em>sh</em>ell. I loved it. It was so well-designed,
with excellent defaults and simplified setup for those things that I
needed to customize (aliases, for example). I had to relearn the basics
since it didn’t share anything with bash, but that was a strong point.
The basics had been re-imagined and made better.</p>
<p>But, I always would end up needing to work with systems that didn’t have
fish, and I couldn’t bring fish with me. In the back of my mind, I knew
that everything I learned in fish was keeping from learning the same
thing in bash, and I would never get good where I needed to be at my
best; production systems.</p>
<p>The straw that broke the camel’s back was when I wanted to start
automating tasks on production systems. Shell scripting was the best
tool for the job. I’m well-versed in Python and Ruby, having done each
professionally, but neither is as suited for gluing together
command-line utilities as bash. To top it off, fish is weak on
scripting. At the time (don’t know about nowadays), the fish team
admittedly focused on interactive use and encouraged you to look
elsewhere for a scripting language.</p>
<p>I decided that if I were to learn scripting, I would need to immerse
myself in bash, including interactively. As I’ve found out, bash may not
have all the bells and whistles of fish or zsh, but if you configure a
few features under the hood, it’s a perfectly functional and powerful
environment. I’ve finished my learning curve and could switch back to
another shell, but now I have no need. Bash does everything I want, and
does it everywhere I need.</p>
<p>See <a href="/bash/2020/07/06/getting-bash.html">part 3</a>, <em>Getting Bash</em>.</p>If you’re interested, start the series with part 1.How I Bash - A New Series2020-07-02T12:00:00+00:002020-07-02T12:00:00+00:00https://binaryphile.github.io/bash/2020/07/02/how-i-bash-a-new-series<p>So I’ve seen a few shells in my time…everything from the venerable
<a href="https://www.4dos.info/4dinfo.htm">4DOS</a> and csh, to the modern zsh and <a href="https://fishshell.com/">fish</a> (my personal favorite).</p>
<p>Even so, I’m not ashamed to say that I love bash. Or rather, I love
making bash work for me. Bash itself is pretty old, and not all that
loveable. I don’t really care. It’s everywhere, and it’s good enough. I
work on a lot of systems, many of them production. My job isn’t to turn
them into my own personal playground…I get paid to work on systems
with others, and that means taking the system as it comes.</p>
<p>In short, if you work with linux systems, you aren’t doing yourself any
favors by <em>not</em> knowing bash inside and out. And once you do, you’ll
find that you don’t need to reach for many other tools a lot of the
time.</p>
<p>But I’m not blogging to explain everything there is to know about bash.
I’ve written a pretty decent series on approaching bash already (see the
blog index). I’m going to try to write some short entries on how I use
bash. Follow me if you will…</p>
<p>See <a href="/bash/2020/07/06/i-was-scared-of-bash.html">part 2</a>, <em>I Was Scared Of Bash</em>.</p>So I’ve seen a few shells in my time…everything from the venerable 4DOS and csh, to the modern zsh and fish (my personal favorite).