Navigating the CLI

The purpose of this post is to provide a general overview of the command line interface (CLI), and how to interact with it. So far, I have shown many things that you can do from the CLI, but haven’t covered exactly what the CLI is, what options it presents you, and how you can use it powerfully to save time.

What Is the CLI, Anyway?

The technical term for the CLI in Linux is a shell. I cannot find a good reason for why it’s known as the shell, but you could perhaps think of it as the outer interface that the user uses to interact with the system and kernel.

The original UNIX shell was simply called sh, and it exists to this day. Several alternatives and clones have been developed since, the most popular being bash (aka the Bourne Against Shell.)

When you open a Terminal application, it executes the default shell program. In Ubuntu, the default shell is bash. bash (and other shells) do not display anything in particular that they are a separate program, and you have to do a little work to even learn what is running. In Ubuntu, You can find the active shell by running echo $0 in a terminal.

devil@ubuntuVM:~$ echo $0
bash

CLI Keyboard Shortcuts

The very first thing you’ll need is a list of common keyboard shortcuts.

Navigation

  • CTRL + a — Go to the beginning of the line.
  • CTRL + e — Go to the end of the line.
  • ALT + f — Move the cursor forward one word.
  • ALT + b — Move the cursor back one word.
  • CTRL + f — Move the cursor forward one character.
  • CTRL + b — Move the cursor back one character.
  • CTRL + x, x — Toggle between the current cursor position and the beginning of the line.

Editing

  • CTRL + _ — Undo! (And, yes, that’s an underscore, so you’ll probably need to use Shift as well.)
  • CTRL + x or CTRL + e — Edit the current command in your $EDITOR.
  • ALT + d — Delete the word after the cursor.
  • ALT + DEL — Delete the word before the cursor.
  • CTRL + d or DEL — Delete the character beneath the cursor.
  • CTRL + h or BACKSPACE — Delete the character before the cursor.
  • CTRL + k — Cut the line after the cursor to the clipboard.
  • CTRL + u — Cut the line before the cursor to the clipboard.
  • CTRL + d — Cut the word after the cursor to the clipboard.
  • CTRL + w — Cut the word before the cursor to the clipboard.
  • CTRL + y — Paste the last item to be cut.

Processes

  • CTRL + l — Clear the entire screen (or use the clear command).
  • CTRL + z — Place the currently running process into a suspended background process (and then use fg to restore it).
  • CTRL + c — Kill the currently running process by sending the SIGINT signal.
  • CTRL + d — Exit the current shell.

History

  • CTRL + r — Bring up the history search.
  • CTRL + g — Exit the history search.
  • CTRL + p or Up — See the previous command in the history.
  • CTRL + n or Down — See the next command in the history.

Of all the shortcuts above, the most important are:

  • Up & Down
  • CTRL + c
  • CTRL + z
  • CTRL + d

Tab Completion

One of the best parts of the Linux shell is the behavior of the TAB key. It acts as a multi-use command and path completion shortcut.

Let’s say that I’m in a particular directory and want to edit another file quickly. If I know most of the path, I can use TAB along the way to auto-complete portions of the path as I go. Perhaps I want to edit /home/devil/Documents/very_long_filename.txt. Instead of typing the whole thing, I could type nano /hom and then hit TAB. The shell will automatically fill the rest of the path and display nano /home/. I can then type dev and hit TAB again. The command nano /home/dev then auto-completes to read nano /home/devil/. Similarly, I can use TAB to auto-complete the Documents and the very_long_filename.txt portion.

If you ever use TAB and there are multiple results, the screen will flash once. Pressing TAB again will display the list of possible matches.

For example, if I TAB complete the command nano /home/devil/Do, it will display the following:

devil@ubuntuVM:~$ nano /home/devil/Do
Documents/ Downloads/ 

From there, I can choose to type a little more to match Documents.

TAB completion also works for completing commands. If I type le and hit TAB twice, I get the following:

devil@ubuntuVM:~$ le
less      lessecho  lessfile  lesskey   lesspipe  let       lexgrog

Environment Variables

The shell provides the ability to store values in a named variable. These variables can be specific to the shell itself, or to a particular program.

To display a list of variables, use the export command like so:

devil@ubuntuVM:~$ export
declare -x COLORTERM="truecolor"
declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"
declare -x DESKTOP_SESSION="ubuntu"
declare -x DISPLAY=":0"
declare -x GDMSESSION="ubuntu"
declare -x GJS_DEBUG_OUTPUT="stderr"
declare -x GJS_DEBUG_TOPICS="JS ERROR;JS LOG"
declare -x GNOME_DESKTOP_SESSION_ID="this-is-deprecated"
declare -x GNOME_SHELL_SESSION_MODE="ubuntu"
declare -x GNOME_TERMINAL_SCREEN="/org/gnome/Terminal/screen/b1717d12_64e9_48dc_b678_c1f5d6ae1657"
declare -x GNOME_TERMINAL_SERVICE=":1.77"
declare -x GPG_AGENT_INFO="/run/user/1000/gnupg/S.gpg-agent:0:1"
declare -x GTK_MODULES="gail:atk-bridge"
declare -x HOME="/home/devil"
declare -x IM_CONFIG_PHASE="1"
declare -x INVOCATION_ID="6e2cb05fa7d64eb0b9817d000e94a4e1"
declare -x JOURNAL_STREAM="8:35979"
declare -x LANG="en_US.UTF-8"
declare -x LESSCLOSE="/usr/bin/lesspipe %s %s"
declare -x LESSOPEN="| /usr/bin/lesspipe %s"
declare -x LOGNAME="devil"
declare -x LS_COLORS="rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:"
declare -x MANAGERPID="1534"
declare -x OLDPWD
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
declare -x PWD="/home/devil"
declare -x QT_ACCESSIBILITY="1"
declare -x QT_IM_MODULE="ibus"
declare -x SESSION_MANAGER="local/ubuntuVM:@/tmp/.ICE-unix/1827,unix/ubuntuVM:/tmp/.ICE-unix/1827"
declare -x SHELL="/bin/bash"
declare -x SHLVL="1"
declare -x SSH_AGENT_PID="1747"
declare -x SSH_AUTH_SOCK="/run/user/1000/keyring/ssh"
declare -x TERM="xterm-256color"
declare -x USER="devil"
declare -x USERNAME="devil"
declare -x VTE_VERSION="6003"
declare -x WINDOWPATH="2"
declare -x XAUTHORITY="/run/user/1000/gdm/Xauthority"
declare -x XDG_CONFIG_DIRS="/etc/xdg/xdg-ubuntu:/etc/xdg"
declare -x XDG_CURRENT_DESKTOP="ubuntu:GNOME"
declare -x XDG_DATA_DIRS="/usr/share/ubuntu:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop"
declare -x XDG_MENU_PREFIX="gnome-"
declare -x XDG_RUNTIME_DIR="/run/user/1000"
declare -x XDG_SESSION_CLASS="user"
declare -x XDG_SESSION_DESKTOP="ubuntu"
declare -x XDG_SESSION_TYPE="x11"
declare -x XMODIFIERS="@im=ibus"

Wow, that’s a lot of variables! Most don’t matter here, but you can see the format — VARIABLE_NAME=“value”.

If you need to reference the variable later, place the $ symbol in front.

You may set a global variable using export like so:

devil@ubuntuVM:~$ export DEVIL="handsome"
devil@ubuntuVM:~$ export | grep DEVIL
declare -x DEVIL="handsome"

See the previous post on text streams if you don’t know what the | symbol or the grep command do.

You can unset the same variable using unset:

devil@ubuntuVM:~$ unset DEVIL

Here’s how to display the value of a variable using echo:

devil@ubuntuVM:~$ DEVIL=handsome
devil@ubuntuVM:~$ echo $DEVIL
handsome

If you need to run a command that reads a particular variable, you may place it before the command. It will be active until the program completes, and then removed from memory.

Getting Help

Most Linux programs come with options (also called switches) that change the behavior of the program at launch. On the CLI, these are most often shown in the format --option, -o, where either form is acceptable.

Consider the tr program from the previous lesson.

devil@ubuntuVM:~$ tr
tr: missing operand
Try 'tr --help' for more information.

Trying to run tr by itself does nothing, but it gives you a helpful hint that the operand is missing. What is that? Try tr --help to find out more.

devil@ubuntuVM:~$ tr --help
Usage: tr [OPTION]... SET1 [SET2]
Translate, squeeze, and/or delete characters from standard input,
writing to standard output.

  -c, -C, --complement    use the complement of SET1
  -d, --delete            delete characters in SET1, do not translate
  -s, --squeeze-repeats   replace each sequence of a repeated character
                            that is listed in the last specified SET,
                            with a single occurrence of that character
  -t, --truncate-set1     first truncate SET1 to length of SET2
      --help     display this help and exit
      --version  output version information and exit

SETs are specified as strings of characters.  Most represent themselves.
Interpreted sequences are:

  \NNN            character with octal value NNN (1 to 3 octal digits)
  \\              backslash
  \a              audible BEL
  \b              backspace
  \f              form feed
  \n              new line
  \r              return
  \t              horizontal tab
  \v              vertical tab
  CHAR1-CHAR2     all characters from CHAR1 to CHAR2 in ascending order
  [CHAR*]         in SET2, copies of CHAR until length of SET1
  [CHAR*REPEAT]   REPEAT copies of CHAR, REPEAT octal if starting with 0
  [:alnum:]       all letters and digits
  [:alpha:]       all letters
  [:blank:]       all horizontal whitespace
  [:cntrl:]       all control characters
  [:digit:]       all digits
  [:graph:]       all printable characters, not including space
  [:lower:]       all lower case letters
  [:print:]       all printable characters, including space
  [:punct:]       all punctuation characters
  [:space:]       all horizontal or vertical whitespace
  [:upper:]       all upper case letters
  [:xdigit:]      all hexadecimal digits
  [=CHAR=]        all characters which are equivalent to CHAR

Translation occurs if -d is not given and both SET1 and SET2 appear.
-t may be used only when translating.  SET2 is extended to length of
SET1 by repeating its last character as necessary.  Excess characters
of SET2 are ignored.  Only [:lower:] and [:upper:] are guaranteed to
expand in ascending order; used in SET2 while translating, they may
only be used in pairs to specify case conversion.  -s uses the last
specified SET, and occurs after translation or deletion.

GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Full documentation at: <https://www.gnu.org/software/coreutils/tr>
or available locally via: info '(coreutils) tr invocation'

Lots to read there! I don’t expect you to review and understand everything, this is just an example of a typical --help output.

Nearly all programs have a --help switch, so use it often.

A Man, a Plan

The other option is the Linux man command, which is short for manual. Program authors typically provide a man page with the installed software, which can be read and displayed by the man program.

Using tr from above, let’s read the man page.

TR(1)                                        User Commands                                       TR(1)

NAME
       tr - translate or delete characters

SYNOPSIS
       tr [OPTION]... SET1 [SET2]

DESCRIPTION
       Translate, squeeze, and/or delete characters from standard input, writing to standard output.

       -c, -C, --complement
              use the complement of SET1

       -d, --delete
              delete characters in SET1, do not translate

       -s, --squeeze-repeats
              replace  each sequence of a repeated character that is listed in the last specified SET,
              with a single occurrence of that character

       -t, --truncate-set1
              first truncate SET1 to length of SET2

       --help display this help and exit

       --version
              output version information and exit

       SETs are specified as strings of characters.  Most represent themselves.  Interpreted sequences
       are:

       \NNN   character with octal value NNN (1 to 3 octal digits)

       \\     backslash

       \a     audible BEL

       \b     backspace

       \f     form feed

       \n     new line

       \r     return

       \t     horizontal tab

       \v     vertical tab

       CHAR1-CHAR2
              all characters from CHAR1 to CHAR2 in ascending order

       [CHAR*]
              in SET2, copies of CHAR until length of SET1

       [CHAR*REPEAT]
              REPEAT copies of CHAR, REPEAT octal if starting with 0

       [:alnum:]
              all letters and digits

       [:alpha:]
              all letters

       [:blank:]
              all horizontal whitespace

       [:cntrl:]
              all control characters

       [:digit:]
              all digits

       [:graph:]
              all printable characters, not including space

       [:lower:]
              all lower case letters

       [:print:]
              all printable characters, including space

       [:punct:]
              all punctuation characters

       [:space:]
              all horizontal or vertical whitespace

       [:upper:]
              all upper case letters

       [:xdigit:]
              all hexadecimal digits

       [=CHAR=]
              all characters which are equivalent to CHAR

       Translation  occurs if -d is not given and both SET1 and SET2 appear.  -t may be used only when
       translating.  SET2 is extended to length of SET1 by repeating its last character as  necessary.
       Excess  characters  of SET2 are ignored.  Only [:lower:] and [:upper:] are guaranteed to expand
       in ascending order; used in SET2 while translating, they may only be used in pairs  to  specify
       case conversion.  -s uses the last specified SET, and occurs after translation or deletion.

AUTHOR
       Written by Jim Meyering.

REPORTING BUGS
       GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
       Report tr translation bugs to <https://translationproject.org/team/>

COPYRIGHT
       Copyright  ©  2018  Free  Software Foundation, Inc.  License GPLv3+: GNU GPL version 3 or later
       <https://gnu.org/licenses/gpl.html>.
       This is free software: you are free to change and redistribute it.  There is  NO  WARRANTY,  to
       the extent permitted by law.

SEE ALSO
       Full documentation at: <https://www.gnu.org/software/coreutils/tr>
       or available locally via: info '(coreutils) tr invocation'

GNU coreutils 8.30                          September 2019                                       TR(1)

This looks very familiar, and a lot of the same options from tr --help appear here. It also has some helpful copyright information, an author bio, publish date, as well as links to find more information about the program.

You can navigate man similar to less, using arrow and pgup/pgdown keys.

Newsletter

Tip Jar

If you're getting value from my writing, please support my efforts with a donation. You can donate directly using my public Ethereum address bowtieddevil.eth. Or you can use the donation button below, which works through my self-hosted BTCPay Server.
linux 

See also