Clarity trumps efficiency.
*I would've liked to write this essay to be understandable for someone without a programming/Linux background, but it was a bit too difficult. If you skip to the paragraph beginning with "...", it gets a bit easier from then on.
If youâve ever written your own shell scripts you may have heard of the phrase âuseless use of cat*â, or less tactfully, âcat abuseâ. This refers to the practice, common among new shell script enthusiasts, of writing commands like âcat file.txt | grep nameâ, when âgrep name file.txtâ would serve perfectly well. Tools like shellcheck will bug you about itâalong with similar constructions like âps ax | grep Discord | wc -lâ instead of âpgrep -c Discordâ.
Well, Iâm here to defend cat abuse! There are two arguments I see against the cat | grep construction, one of which is valid but situational, and the other of which is completely invalid. The former is that the extra pipe just adds additional overhead into the command. Yes, it does. And itâs unlikely to matter at all if youâre using it on 20KiB text files on a system built in the past 40 years; however, in production, when writing tools that need to be able to deal with arbitrarily large text files as efficiently as possible, sure.
The latter is âwell, itâs just unnecessaryâ. I disagree. I think the cat | grep constructionâalong with similar such as grep | wc, ps | grep, ps | awk, and so onâserves a very important purpose in that it makes shell scripts easier to read, easier to modify, and easier to debug.
Consider this example from above:
ps ax | grep Discord | wc -l
Read the process table; filter for "Discord"; count the number of lines. Itâs very atomic. Each operation can be swapped out for something else without confusing the reader. On the other hand:
pgrep -c Discord
Now, this does the same thingâcounting the number of lines in the process table with "Discord" in them. It looks like only one operation... but itâs really still three in disguise. And worse, imagine you suddenly want to add another filter; sorting not only by Discord, but by processes that include the word âtitleâ. This is not straightforward at all! It turns out that while regex has a standard way of searching for alternatives, it really does not provide an easy method for searching for BOTH of two words. On the other hand, with the atomic version, itâs easy:
ps ax | grep Discord | grep title | wc -l
Take that, âuselessâ use of cat.
Thereâs a broader meaning, though, to my statement of âclarity trumps efficiencyâ. I apply it to every aspect of use of electronics, from web searches to backup routines to yes, silly little shell scripts that use cat.
I use command aliases, but to a pretty limited degree; I avoid cutesy stuff like âllâ for âls -lâ and âyeetâ for âpacman -Rnsâ, along with possibly-dangerous substitutions like ârmâ for ârm -iâ; Iâd never dream of aliasing ânanoâ or âviâ to my preferred text editor (vim). I believe strongly that my commands should be transparent, and saving me from my own muscle memory once or twice is not worth making them completely opaque.
Tab completion on the other hand is one of my favorite features in the shell. Itâs the perfect combination of transparent and convenient; without having to alias any of my application names or get hit by the information overload fuzzy finding gives you, I can still launch any of them in no more than four keystrokes. (Except audacious and audacity, admittedly.)
I use a floating window manager (Openbox), and when I need to briefly use a tiling layout, I have a very boring way of doing so: focusing each window one by one and moving it into the slot I want. (While holding down the Super/Windows key, 1-C-2-V does a basic left-right split.)
... I make some use of spellcheck on assignments to be turned in, but never autocorrect, which I abhor even in messaging apps. Every change to your inputs should be deliberate; otherwise youâll never learn what youâre doing wrong, and youâll never need to be precise because youâve turned over that part of your brain to the algorithm.
This leads me to an important corollary of my principle: âitâs better to have a slow algorithm that you understand, than a fast one that you donâtâ.
Satya Nadellaâs vision of the PC of the future is one where you tell it what to do in natural language and it interprets that using LLMs and so on into machine instructions. Instead of viewing a PC as a toolbox you go into the workshop with, and work on projects with in certain defined ways, he wants the PC to be an assistant; you give the assistant directions and pray that it gets things right. Of course you arenât allowed into the workshop with the tools anymore; thatâs the assistantâs job!
Anyone whoâs used Google Search over the past ten years knows how miserable this model is; you search for a specific phrase that Google âhelpfullyâ corrects to something it thinks you meant. There was a learning curve to the old way, but once you learned how to state queries precisely, you were done; now you need to play psychologist, sociologist, and statistician all at once.
This is a decent part of why I dislike generative AI, though far from the main reason. I donât want an opaque algorithm making decisions for me, unless those decisions are incredibly low-level stuff like core parking that no human should be directly involved with in the first place.
To get back to my own setup, I have a whole text file documenting the system maintenance process I go through once every month; most of it could be automated, but I make every step a deliberate choice. Not to go all new-age, but for me specificallyâit all ties back in to mindfulness.
I think people have only a vague concept of what mindfulness is. Until two years ago or so, I was the same way. But to who I am now, mindfulness means not doing anything on autopilot. Instead of letting yourself half-doze off on a drive home, scarcely remembering the 20 minutes from the parking lot to the garage, be conscious of every turn. Instead of immediately putting on music and blocking out the world on a train ride to the next city, force yourself to be present in the train car, and notice the way the light reflects on the plastic seat two rows in front.
And to me, clarity in code, and in UX, is a part of this mindfulness. Programs that are easy to read, easy to modify, and easy to debug encourage you to look closerâto consider every atom that goes into their statements instead of taking them for granted. Slow algorithms that you understand can help you think of improvements; fast algorithms that you donât encourage you to give up and leave the real thinking to someone else.
So write silly little shell scripts with five pipes in a single statement, and yes, that uselessly use cat. Rather than doing anything wrongâyouâre allowing yourself and others to think, to try, and to improve.









