More Useful Utilities
So far, we have a small but powerful list of commands:
cd
,ls
,mv
,touch
,rm
,mkdir
,rmdir
, andpwd
for information and basic manipulation of the file systemwhich
for finding the location of programsenv
andexport
for environment variables and setting new variablesecho
for printing values to the screen, such as variables after expansion
In this chapter, we'll look at a variety of other commands that you'll likely encounter as you use the terminal more in your development journey.
Command Manuals with man
Since I want this book to stay a reasonable length, I only briefly introduce the commands here. But, as the saying goes, "if you teach a developer one pattern for a command they can use that one pattern, but if you teach a developer to check the manual, they can use all the patterns". Maybe I just made that up, actually.
For many system commands, you can use the man
command (short for "manual") to
pull up a fancy interactive manual:
[stephen@virtualbox ~] man man
MAN(1) Manual pager utils MAN(1)
NAME
man - an interface to the system reference manuals
SYNOPSIS
man [man options] [[section] page ...] ...
man -k [apropos options] regexp ...
man -K [man options] [section] term ...
man -f [whatis options] page ...
man -l [man options] file ...
man -w|-W [man options] page ...
DESCRIPTION
man is the system's manual pager. Each page argument given to man is normally the name of a program, utility or function. The manual page associated with each of these arguments is then found and
displayed. A section, if provided, will direct man to look only in that section of the manual. The default action is to search in all of the available sections following a pre-defined order (see
DEFAULTS), and to show only the first page found, even if page exists in several sections.
The manual pages are built in to most Linux systems for all the common commands and many more uncommon commands too. They contain command descriptions, usage examples, documentation of options, and pretty much all the information you might need for most uses of each command.
Navigating the manual pages with the up and down arrow keys is possible, but
slow. Instead, man
allows you to use the same key bindings as less
, a useful
program used for viewing files and long outputs. To summarize:
d
moves "down" one-half page, whileb
moves "back" one half-pageu
moves "up", but by one full page instead of half-page/
allows you to search for specific text. For example, if I wanted to know what the-i
option forman
does, I can type:/-i
and press Enter, it will highlight the matches and jump the view to the first match- As an example:
- If you have searched for text with
/
, you can usen
to jump to the next match andN
to jump to the previous match q
will quit the programg
by itself will move to the top of the file, or if you provide a number and then typeg
, you'll move to the line number providedG
by itself moves to the bottom of the file, or with a number does the same asg
Alternative Naming with alias
Sometimes, you may want to give a command you use frequently a "shortcut"
command to save time. You can use the alias
command to do so:
~
bsh ❯ alias me='echo "Hello there, $(whoami)!"'
~
bsh ❯ me
Hello there, stephen!
Nifty!
To set these every time you open your shell, you can just put alias
commands
in your .bashrc
file. Although you shouldn't overuse aliases, a light
sprinkling of them can be very helpful and productive!
If you want to see all the aliases you have defined, you can run alias
by
itself:
~
bsh ❯ alias
alias g.b='git branch -v --sort=committerdate'
alias g.c='git commit -v'
alias g.co='git checkout'
alias g.cv='git commit --no-verify -v'
alias g.d='git diff'
alias g.log='git log --graph --format=format:'\''%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(bold white)— %an%C(reset)%C(bold yellow)%d%C(reset)'\'' --abbrev-commit --date=relative'
alias g.p='git pull -r'
alias g.pf='git push --force-with-lease'
alias g.s='git status'
alias g.tree='git log --graph --pretty=oneline --abbrev-commit'
alias ls='eza -G'
alias src='source__'
alias vim='nvim'
Maybe I should clean these up sometime...
Search for Files with find
The find
command allows you to search for specific file names in specific
directories. The general usage looks like:
find <directory> -name <file_name>
find . -name cat_names.csv
find /bin -name ls
find
is extremely flexible and has a variety of modes of operation. You can
search for directories instead:
# find all directories in the current directory
find . -type d
You can use what's called a glob to search for files by their file extension:
find . -name '*.csv'
And you can filter by size, owner, modification date, and more.
Search Through Files with grep
Sometimes you want to find lines matching a pattern in a specific file or files.
For this, you can use the grep
command, which has a funny name originating
from a common command in an older tool.
grep <pattern> <files>
[stephen@virtualbox ~] grep export .bashrc
*) export PATH="${PATH}:${new_path_entry}" ;;
export LLVM_INSTALL_PATH="/home/stephen/local/llvm16-release"
export FLYCTL_INSTALL="/home/stephen/.fly"
export FZF_DEFAULT_COMMAND='rg --files'
This example searches my system configuration file called .bashrc
for any
lines that contain the text export
. Although there's some mystery in the
format, you can see that I use export
in 4 different places in this file.
Let's try another example:
[stephen@virtualbox ~] grep PATH .bashrc
case ":$PATH:" in
*) export PATH="${PATH}:${new_path_entry}" ;;
export LLVM_INSTALL_PATH="/home/stephen/local/llvm16-release"
path_add "$LLVM_INSTALL_PATH/bin"
path_add "$FLYCTL_INSTALL/bin"
Notice that although I searched for "PATH", it also printed out lines that have
"PATH" as part of another "word", like "LLVM_INSTALL_PATH". You can make it only
look for "whole" words with the -w
option:
[stephen@virtualbox ~] grep PATH .bashrc -w
case ":$PATH:" in
*) export PATH="${PATH}:${new_path_entry}" ;;
You can also print out the line numbers of each matching line with -n
:
[stephen@virtualbox ~] grep PATH .bashrc -n
43: case ":$PATH:" in
45: *) export PATH="${PATH}:${new_path_entry}" ;;
51: export LLVM_INSTALL_PATH="/home/stephen/local/llvm16-release"
63: path_add "$LLVM_INSTALL_PATH/bin"
64: path_add "$FLYCTL_INSTALL/bin"
And you can make the pattern match on any combination of uppercase and lowercase
with -i
:
[stephen@virtualbox ~] grep PATH .bashrc -i
path_add() {
new_path_entry="$1"
if [ -n "$new_path_entry" ]; then
case ":$PATH:" in
*:"${new_path_entry}":*) ;;
*) export PATH="${PATH}:${new_path_entry}" ;;
modify_paths() {
export LLVM_INSTALL_PATH="/home/stephen/local/llvm16-release"
zig_paths
path_add "/usr/local/sbin"
# more of the above...
modify_paths
There are quite a few other options you can find in the man
page!
The Pipe Operator |
Sometimes, you'll want to use the results of one command to feed into another command. Perhaps you want to get all the text files in your directory and order them by the file name. How would you do this? Well, we can use the pipe operator! So named because, well, it looks like a vertical pipe, and it sends data between commands. We could use it like this:
find . -name "*.txt" | sort
The sort
command, as you may expect, sorts the strings it receives
alphabetically and numerically, like a dictionary does.
However, if we have text files in a subdirectory, this doesn't quite work:
bsh ❯ find . -type f
./sample/file5.txt
./file1.txt
./file6.txt
./file2.txt
./file4.txt
./file3.csv
bsh ❯ find . -name "*.txt" | sort
./file1.txt
./file2.txt
./file4.txt
./file6.txt
./sample/file5.txt
We would expect "file5" to be before "file6", but because of the subdirectory,
"file6" shows up first. To fix this, we can use a command basename
:
bsh ❯ basename sample/file5.txt
file5.txt
What happens if we put this before sort
in the pipe?
bsh ❯ find . -name "*.txt" | basename | sort
basename: missing operand
Try 'basename --help' for more information.
Well, that's not what we want. We can't use it directly, but we can use another
tool called xargs
to build a command from the results of the previous command:
bsh ❯ find . -name "*.txt" | xargs basename -a
file5.txt
file1.txt
file6.txt
file2.txt
file4.txt
The -a
option tells basename
to take multiple arguments and operate on them
individually. And now, it works! They're out of order, but we can just slap a
sort
at the end:
bsh ❯ find . -name "*.txt" | xargs basename -a | sort
file1.txt
file2.txt
file4.txt
file5.txt
file6.txt
And now we know all the text files in and below our current directory, and they're sorted!
Simple Text-editing with nano
The most common thing you'll do in a typical software development career is
typing text. For that, you'll need a text editor, and I think nano
is the
simplest one to start with. To start it, run:
nano <file_name>
As an example, I ran this to open one of my terminal configuration files:
nano .bashrc
What I like about nano
is the always-present control scheme guide at the
bottom of the screen. The commands starting with ^
indicate the Ctrl
key,
starting with M
indicates Alt
, and although it's not a power tool, it colors
text in the file based on the file type, and enables basic editing.
Outside of the special commands at the bottom of the screen, nano
works
exactly like Notepad or Google Docs, just without formatting. Typing adds
characters to the file, while Backspace and Delete remove characters from the
file. Shift accompanied by movement with the arrow keys or the back/forward/next
word/previous word commands selects an area of text that you can cut, copy, and
paste.
It's pretty simple, but effective.
Complex Text-editing with emacs
or vim
This section could easily be multiple encyclopedias' worth of introduction, so
this is just a brief note on the world of text editors. In the terminal world of
editors, emacs
and vi
are the two historical options. vi
itself isn't used
much today, but it inspired vim
, which later spawned my personal choice of
editor, Neovim
.
You might not know that the two editors have a very contentious history in what's called the editor war. Software developers have held very strong opinions for a long time.
Whether you choose to use a terminal editor or a GUI editor, just remember that
whatever you enjoy using is the best tool for you! Some developers vibe better
with vim
or emacs
, some will prefer something like Visual Studio Code, and
some will enjoy a more full-feature solution like JetBrains or Visual Studio
(distinct from Visual Studio Code).
Lists for Further Reading
If you want to see a different list of a lot of terminal commands, there's a great list from DigitalOcean on the top 50+ commands! That's a lot!