Command Line

Command line broadly means a text based prompt for running software on a computer. I am primarily concerned with Unix-like shells, rather than say Microsoft/Window’s command line interfaces such as PowerShell. In modern GUIs, you often will be using a terminal emulator in lieu of a direct terminal for accessing the command line. An important convention in the command line is configuration via dotfiles.

Choosing a shell

Choosing between the various unix-compatible shells is important for day-to-day interactions with the command line and also compatibility of any shell scripts you write. In most cases, and most scripts, the shells will behave similarly and so the choice boils down to user preference and audience/usage for shell scripts.

/bin/sh is the system shell, classically it was the bourne shell, and the assumption is that it will be bourne shell compatible. Depending on the unix distribution, it may be the bourne shell, Almquist shell (ash), on Ubuntu it may be dash1 (a port of the ash shell), or it may be the bourne again shell (bash).

For day-to-day interactions

For day-to-day interactive use on the command line, most people will select a superset shell of sh that provides more features and niceties. Some options:

  • bash, is ubiquitous and in many cases people will refer to the shell as bash. bash is a common default on many distributions and *nix like environments.
  • fish is a feature rich shell with many of those built-in features target at interactivity and usability.
  • zsh is my personal preference and became the default for macOS with Catalina2.
  • murex is a shell for DevOps with usability improvements written in Go (lang)

For Shell Scripting

Selecting a shell for scripting depends on the expected execution environment for the scripts. If it is for your internal use, just use the your own shell or bash. If you are trying to maximize portability, target ksh or ash.

Notable mentions

  • The C shell (csh), or the improved version tsch, is the default for root users on FreeBSD, while the Almquist shell (ash) is the default for users.
  • KornShell (ksh) is favored by some for scripting for it’s portability/stability
  • rsh is a hobbyist shell written in ruby

Specific Tools

Essentials

There are a hand full of tools that must be learned in order to be proficient at the command line. These are largely around navigating or basic file manipulation. Use cd for changing directory and navigating across file system. Once in a directory, use ls to list the contents of a given directory and attributes about the files within it. Alternatively, the find command for finding files within a file tree. Once a file is located, cat for outputting a file to STDOUT, although you are more likely better off using a paging a program such as less if you just want to read the contents of a file. You can copy the file with cp or move/rename it with mv. At any point, if you get lost, man can be used to get the manual page of any command. Many people favor tldr for this purpose as it gives quick usable examples. grep for finding text within files and standard output. echo will output whatever is passed, this is most useful for inspecting environmental variables outside of scripting. For example, echo $SHELL will output the currently set shell. ssh is used to for connecting to remote systems securely (secure shell). rsync to synchronize two locations (can be local or remote) efficiently.

Outside of that, the operating system may have specific tools, for example macOS Command Line Tools.

Advanced

  • tmux or Zellij for terminal multiplexing
  • awk
  • jq
  • pandoc
  • xargs for relocating piped output to different spots within the following command
  • pv is the pipe viewer tool for monitoring the progress of data through a pipeline
  • alt - Find alternate path for a provided path
  • tokei - Code statistics
  • direnv - set directory specific environment

Highly Specific

  • bandwhich
  • 7zip
  • exiftool
  • fx - JSON viewer tool, similar to jq
  • just
  • jsc
    • Javascript commandline tool bundled with macOS3
  • johnkerl/miller
    • Miller is like awk, sed, cut, join, and sort for name-indexed data such as CSV, TSV, and tabular JSON
  • navi
  • rmlint - find and remove duplicate files
  • tv - csv pretty printer for the command line
  • topgrade - tool for keeping up to date across multiple package managers
  • youtube-dl
    • yt-dlp Fork with additional features and extractors

Scripting

Improving command line ergonomics

You can choose a variety of colors to your suiting. Replacements for common command line tools

  • RESH (Rich Enhanced Shell History) adds better history ergonomics to zsh and bash
  • Tealdear is a rust implementation of tldr for CLI cheat sheets
  • navi is a rust cheatsheet manager
  • Starship is a prompt across terminals
  • moreutils is a set of useful commandline tools4, one of which is sponge for reading the entire input before preceding
  • Pure is a minimal zsh prompt
  • powerlevel10k is a zsh theme
  • zoxide, fasd, z
  • dot
  • fzf
  • just - a command line runner. Useful when you have a handful of commands you run in a project folder regularly. Like a simpler make because it is not a build system
  • Font options: you can patch your font to add icons that will be displayed on the command line using NerdFont.
    • Fonts are largely a matter of personal preference, however it’s worth considering adding ligature support. Some fonts worth checking out are FiraCode and PragmataPro
  • Tyler Cipriani has several easy functions, like calc and temperature that can be added for quick reference on the command line5.

Tutorials

Creating a command line GIF

terminalizer is a javascript program that can be used to create a GIF from a terminal session.

I had to use this config:

# Specify a command to be executed
# like `/bin/bash -l`, `ls`, or any other commands
# the default is bash for Linux
# or powershell.exe for Windows
command: zsh

# Specify the current working directory path
# the default is the current working directory path
cwd: null

# Export additional ENV variables
env:
  recording: true

# Explicitly set the number of columns
# or use `auto` to take the current
# number of columns of your shell
cols: auto

# Explicitly set the number of rows
# or use `auto` to take the current
# number of rows of your shell
rows: auto

# Amount of times to repeat GIF
# If value is -1, play once
# If value is 0, loop indefinitely
# If value is a positive number, loop n times
repeat: 0

# Quality
# 1 - 100
quality: 100

# Delay between frames in ms
# If the value is `auto` use the actual recording delays
frameDelay: auto

# Maximum delay between frames in ms
# Ignored if the `frameDelay` isn't set to `auto`
# Set to `auto` to prevent limiting the max idle time
maxIdleTime: 2000

# The surrounding frame box
# The `type` can be null, window, floating, or solid`
# To hide the title use the value null
# Don't forget to add a backgroundColor style with a null as type
frameBox:
  type: floating
  title: null
  style:
    border: 0px black solid
    # boxShadow: none
    # margin: 0px

# Add a watermark image to the rendered gif
# You need to specify an absolute path for
# the image on your machine or a URL, and you can also
# add your own CSS styles
watermark:
  imagePath: null
  style:
    position: absolute
    right: 15px
    bottom: 15px
    width: 100px
    opacity: 0.9

# Cursor style can be one of
# `block`, `underline`, or `bar`
cursorStyle: block

# Font family
# You can use any font that is installed on your machine
# in CSS-like syntax
fontFamily: "PragmataPro Mono Liga"

# The size of the font
fontSize: 20

# The height of lines
lineHeight: 1

# The spacing between letters
letterSpacing: 0

# Theme
theme:
  background: "#2f333e"
  foreground: "##c7c7c7"
  cursor: "#d9dde7"
  black: "#3c4150"
  red: "#b2656b"
  green: "#a8bd90"
  yellow: "#e5cc93"
  blue: "#87a0be"
  magenta: "#ae8fab"
  cyan: "#93becd"
  white: "#e5e8ef"
  brightBlack: "#4d5568"
  brightRed: "#b2656b"
  brightGreen: "#a8bd90"
  brightYellow: "#e5cc93"
  brightBlue: "#87a0be"
  brightMagenta: "#ae8fab"
  brightCyan: "#98baba"
  brightWhite: "#eceef3"

References

1.
DashAsBinSh - Ubuntu Wiki. Ubuntu wiki at https://wiki.ubuntu.com/DashAsBinSh.
2.
Use zsh as the default shell on your Mac. Apple support at https://support.apple.com/en-us/HT208050.
3.
Hockenberry, C. Jsc: My New Best Friend $\bullet$ furbo.org. at https://furbo.org/2021/08/25/jsc-my-new-best-friend/ (2021).
4.
Hess, J. Moreutils. at https://joeyh.name/code/moreutils/.
5.
Cipriani, T. Cool desktops don’t change. at https://tylercipriani.com/blog/2022/06/15/choose-boring-desktop-technology/ (2022).

Links to this note