After about half a decade of daily driving Linux, I have come to understand why the command line is simply better.
When I first started down the rabbit hole, I thought that the cli was kind of “hipsterish” and what “the cool kids” were doing - So much so that I put it on the back burner for the first year or so. But, when moving to my first window manager (i3) it made sense to go all in on the “Linux way” of doing things. I have never looked back.
The beauty of Linux is that you can choose how to use the computer, it is yours. So, GUI alternatives are a good thing - they help people start the journey towards freedom away from the Windows and Macs of the world. As such, you won’t find me knocking GUI programs, they have their place, and frankly, they are also better in some use cases; Browsing the modern web, image and video editing, and allowing the artistic side of design to show through are some of them. With CSS, you are able to bring in expression and full customization that plain text doesn’t allow.
But, over time, I warmed up to the command line. There were many reasons that I’ll cover below - but I came to find CLIs as actually easier to use after the learning curve.
Let’s discuss.
Speed, Efficiency and Customization #
One thing that you come to realize in this computing journey is that the GUI apps that 90% of people use are just a slower way of doing things.
Sure, you are limited in the CLI by the speed with which you can move your fingers, but that is not the end of the story. If it was, I would just say “learn to type faster” and end this post at that.
No no.
Command lines allow you to find speed in the tooling they offer, the additional functionality of scripting and aliasing, and when that fails, they allow you to create whatever you want - my .zshrc is different than everyone eles’s, and through years of seeing what other people are doing and stealing the best parts, I have a comprehensive and tailored environment that is perfect for me.
Power, Control and Reproducibility #
The command line is tremendously powerful to the point that you won’t even look at the overly engineered desktop apps in the future - they play second fiddle to the underlying tool that is being used. They are a wrapper over the command line in many cases! You can explicity tell the program to perform in the way you want, and the error logging is superior than GUI alternatives in the vast majority of cases.
Unfettered Potential #
I have looked to the CLI for nearly all the apps I use. When you become a power user of unix systems, you see the unlimited potential staring back at you from the screen, and it dares you to dive in.
You will come to see that the command line is a place of creativity and building on the shoulders of giants. Taking the amazing tools that were created before you and using them to do exactly what you want them to do.
And for the rabbit hole diver like myself, this is a journey not a destination. You will never know all there is to know about the CLI. You’re in it for life.
And in the words of Neal Stephenson, In the Beginning… Was the Command Line
What I use in the Command line #
Basic Tooling #
When you first learn to use the command line, you’ll learn about the basic unix commands of Gd, ls, cat, pwd, mkdir, touch, cp, mv, rm, find and grep.
These tools are default for a reason - they do exactly what you need them to do, get you where you need to go, and in seeing that you can tie the output into another program, you start to see the power.
They’re only the beginning of the story though.
Advanced tooling #
While the basic unix tooling is great and will get you far, there are some even better tools that exist.
rg can replace grep
exa can replace ls and automatically show your file structure when you move about the filesystem
bat can replace cat
fd can replace find
We can use aliases to update our basic tooling to the more advanced tools:
alias ls="eza -l --icons"
alias cat="bat"
Zoxide is a good cd alternative that remembers where in your filesystem you most commonly go and adds in suggestions when you want to move quickly. I still use traditional cd
to get home, but z
when I want to get deep into the filesystem.
Aliases #
Have a place in your file system you go all of the time? A command you find yourself typing out all day long?
Create an alias for it!
A great example is this:
I find myself wanting to see the networks when out and about. The command to do this is nmcli device wifi list
which uses network manager’s cli to list the wifi networks your computer can see. Not the longest command in the world, but annoying to type out nonetheless. So, let’s make an alias for that:
alias nmlist="nmcli device wifi list"
Now when we type out nmlist
, we are essentially using the longer command without typing it. Nice!
File manager #
These can get you anywhere you need to go, but you can also go further with TUI file managers that make this even easier. Many people use ranger, and for the first few years I used a Linux system, this was my choice, too. You can easily use Vim movement to get around your filesystem, build in image and file previews, and extend the tool in numerous ways. The only thing is that is is written in python, and this means that it can be slow at times.
Enter, lf, vifm, nnn, and one of dozens of different programs.
The one I landed on and have been happily using for the past year or so is yazi. Written in rust, it is fast, has built in image/file previewing, and does everything I want a manager to do out of the box.
In most cases however, a file manager isn’t needed when you become proficient with the command line, and I am using this less and less these days. What I am using is…
FZF #
FZF is a massively impactful tool that allows a user to search, preview, and do many amazing things. Not only this, but you can pipe it in to various other commands to create an interactive blazingly fast search and find.
I have a custom “fcd” hook in my .zshrc that looks like this (credit to Bugswriter on Youtube for this idea):
fcd() {
cd "$(find -type d | fzf --preview 'tree -C {} | head -200')"
}
that will allow the user to quickly see directory structure and move to it:
Shortcut history searching #
Ctrl + r has always been a great way to see your command history, but add in fzf support and see how easily searchable that history really can be:
ZSH Plugins #
While I may get shouted down by the purists, there are some plugins that I use to quickly move about the filesystem and perform actions that are otherwise tedious. Some of these plugins include:
docker
git
fzf-tab
zsh-autosuggestions
zsh-syntax-highlighting
systemadmin
pass
All of these include autocomplete for commonly used programs, fzf completion and search for thesei functions, and more. This is a rabbit hole unto itself so we won’t go too far. But, you can!
Lazygit #
Leaving emacs meant leaving behind the awesome Magit git interface. Luckily, lazygit exists, and it is really good, so much so that I don’t miss magit at all. It looks like this:
Scripting #
Scripting is another rabbit hole unto itself, and one that I am admittedly just getting into. The jest is this - your command line is incredibly powerful because the programs within it can take output from one and insert it into another via a process called “piping”.
What this means in laymans terms is that you have the ability to build a program from other programs very easily. Want to take the output of a search and insert it into a file? Done:
#!/bin/bash
# Perform the fzf search
selected=$(fzf)
# Check if a selection was made
if [ -n "$selected" ]; then
# Ask for the output file name
echo "Enter the name of the output file:"
read output_file
# Write the selection to the file
echo "$selected" > "$output_file"
echo "Selection saved to $output_file"
else
echo "No selection made."
fi
Advanced and anecdotal use cases: #
Uploading pictures #
I use cloudinary as my image hosting platform, and as such, upload numerous images to it daily. So, why not create a simple script that permits me to do this?
I took inspiration from the catbox script
#!/bin/bash
# Cloudinary credentials
CLOUD_NAME="secret"
API_KEY="also_secret"
API_SECRET="also_also_secret"
# Cloudinary upload endpoint
UPLOAD_URL="https://api.cloudinary.com/v1_1/$CLOUD_NAME/image/upload"
# Set the directory to search for images
IMAGE_DIR="$HOME/Pictures"
# Create a temporary file to store the selected file path
TEMP_FILE=$(mktemp)
# Use Yazi to select an image
yazi --chooser-file "$TEMP_FILE" "$IMAGE_DIR"
# Read the selected file from the temporary file
SELECTED_FILE=$(cat "$TEMP_FILE")
# Remove the temporary file
rm "$TEMP_FILE"
# Check if a file was selected
if [ -z "$SELECTED_FILE" ]; then
echo "No file selected. Exiting."
exit 1
fi
# Get the filename
FILENAME=$(basename "$SELECTED_FILE")
echo "Selected file: $FILENAME"
# Upload to Cloudinary
RESPONSE=$(curl -s -X POST -F "file=@$SELECTED_FILE" \
-F "api_key=$API_KEY" \
-F "timestamp=$(date +%s)" \
-F "signature=$(echo -n "timestamp=$(date +%s)$API_SECRET" | sha1sum | awk '{print $1}')" \
"$UPLOAD_URL")
# Extract the URL from the response
URL=$(echo "$RESPONSE" | grep -o '"url":"[^"]*' | sed 's/"url":"//')
if [ -n "$URL" ]; then
echo "Upload successful!"
echo "Image URL: $URL"
else
echo "Upload failed. Response:"
echo "$RESPONSE"
fi
Now, I simply call this script to upload an image to my hosting service, copy the output url, and insert it into the post or app I am building out. No more clunky web inteface!
Browsing the web #
Now, this is a little esoteric, but one can even browse the web from the command line using browsers like browsh or more classically lynx.
If you are sick of the bloat of the modern web, then this is for you. I’m not saying that your experience will be seamless or even enjoyable, just that it is possible. In the days of the old web, where pages were just text and links, this would have been perfect, but truly only gopher or gemini adhere to this now, minus some purists.
What are your tools you are using in the command line? Send me an email to discuss.
Until next time.