Table of Contents
Introduction
The shell is the program that allows a user or another program to interface with the operating system’s internal services and system programs. In a Unix-based system (i.e. any Linux Distribution (or distro for short), mac OS, OpenBSD, etc.) the base shell is normally accessed through the terminal; in any NT-based operating system (anything Windows) the base shell is access through the command line (cmd). The graphical user interface (GUI) of an operating system could technically be considered a shell as well, but does not easily allow for the automation repetitive tasks, and thus is a little useless in power computing or harnessing the full potential of your computer. If you are interested in learning more about different types of GUIs, this article is a good read and can help you prettify your distro! But if you are interested in tackling the the terminal and become proficient in your shell abilities, this is definitely a good place to start.
Why should I use the shell?
There are a number of different reasons why using the shell is advantageous in power computing, especially when creating specialized systems centered around your own custom software or setup. If you ask the average Linux user why bothering with the terminal is important, you’ll likely hear some of these reasons:
- It’s faster
- It’s more powerful (i.e. batch operations, such as deleting multiple files with a specific pattern, etc.)
- Facilitates automation (i.e. scheduled tasks, scripting, etc.)
- Easy remote access
- You look like a cool hacker 😎
While all of these reasons are valid and should definitely be pursued, using the shell in a research environment requires a more in-depth exposure. Although this may sound intimidating at first, with a little time and Googling, a mastery of the shell will allow you to:
- Understand the inner workings of most operating systems
- Design intelligent systems
- Open horizons into hardware hacking/integration
- Sound like a cool hacker 😎💻
Choose your weapon
Fast-forwarding through a dry and nerdy explanation of who made what shell and why that is super exciting, we will take a look at the current popular shell programs that exist at the time of this writing. What? You can change your shell? Why would I even want to do that when what I use right now works perfectly well? All very valid questions. Maybe I can convince you with two pictures:
Here we have the default shell in Ubuntu 20.04:
This is using the vanilla (i.e, not plugins added or preferences changed) Bourne Again SHell (bash).
Next up we have the shell configuration I personally use (still in Ubuntu 20.04):
This is using the Z Shell (zsh, pronounced ‘zeesh’) with the Powerlevel10k theme on Oh My Zsh, using NerdFonts for the fun glyphs. You’ll also notice an inclusion of a timestamp of the last command entered and a status icon to indicate the return code of the previous command (if everything is okay, or 0, the default glyph is the green checkmark). If these things seem more like distractions rather than enhancements or you are simply content with the basic setup, feel free to skip to the next session.
So far this just looks like a theming difference, no? Well, its this theming that allows you to enjoy some pretty powerful tools that you wouldn’t get otherwise. For example, lets do a little versus session just between vanilla bash and the my zsh setup to get an idea of some basic perks of modding your shell:
Git Repositories
In vanilla bash, it is hard to see when you are in a git repository as opposed to a normal directory:
This doesn’t seem like too bad of an issue, right? Wrong. Anyone who has worked with git repos will know that when you make accidental changes to files inside of a repository, it can be downright terrible to try and revert the files their previous state.
Lets compare this to the zsh setup from above with the same directory’s prompt:
Not only is there a little section with an icon that shows a branch and the GitHub icon, it also gives an indicator on how many uncommitted files exist without you ever needing to enter git status
just to see if anything has changed.
Python Environments
This seems more like a nit-picky difference to me, but I think it is worth including just the same. Python environments are neat containers that allow you to install project-specific libraries within its own confined space. Knowing when you are in one of these environments is critical to your project seeing as you could install a library on the general system unsuccessfully and end up ruining your whole operating system as a consequence (true story).
In bash, the indicator for the pyenv is prepended to the normal prompt you get in any other directory. Though this might not be true for everyone, it was certainly easy enough for me to miss:
Although it is not too big of a difference, my current zsh theme takes a different approach in placing the name of the environment you are in:
By having the name of the pyenv in a different location, the eye is drawn to information which takes up normally empty space in the default prompt, making the fact that you are in a pyenv a little more noticable. Like I said, nit-picky, but helpful nonetheless.
Command History
In any basic shell, you can use the history
command to view a buffer of all commands entered inside the shell environment. Alternatively, you can also use the up arrow to scroll through the last entered commands. For many people, this seems to work well enough, after all, it the default behavior on bash:
Zsh’s control of searching through command history is a little more intelligent. Instead of of just being able to scroll through command history, you can also scroll through a filtered history chronologically. All that is different is that you need to type in the desired pattern before hitting the up arrow:
Whether this is fascinating to you or not, these are just a few perks that come from a very specific setup. Thankfully, the opensource is vast and very creative, which means that even if these perks don’t tickle your fancy, odds are there is something that will! Below is a table of common shells that are in use today, all with their varying pros and cons. If you are feeling adventurous enough, install a few of them on your machine and see which one feels the best!
*nix-compatible Shells
Shell | Description | External Site |
---|---|---|
Bourne Shell (sh) | The evolution of the original shell developed by Thompson (one of the authors of the C programming language). This is the most basic shell you will be greeted with when remoting into a Linux-enabled, embedded machine. Elements of this shell’s syntax are found in most others. | N/A |
Bourne Again SHell (bash) | Shell that is used in Debian-based distros, which seems to be an enhancement of the Bourne Shell as the name denotes. This shell comes default on Ubuntu | https://www.gnu.org/software/bash/ |
Debian Almquist SHell (dash) | Shell that is default in the Debian Linux distro. Similar to sh with few syntactical changes | https://www.in-ulm.de/~mascheck/various/ash/ |
TENEX C SHell (tcsh) | Shell that is sh-like which is the default shell program on all BSD-based systems. | https://www.tcsh.org/ |
Z SHell (zsh) | Enhanced version of Bourne Again Shell with a wide variety of plugins, customization including command specific history. | https://www.zsh.org/ |
Korn SHell (ksh) | Middle of the road between the tcsh predecessor (csh) and sh. | http://www.kornshell.com/ |
Friendly Interactive SHell (fish) | Bash-based shell focused on user friendliness, command suggestions, and command specific auto-completion. | https://fishshell.com/ |
NOTE: In most of the pages for Linux Magic, we will be using the bash/zsh/fish/dash/sh syntax, seeing as most of these shells are the most popular and all have nearly identical syntax.
Basic Navigation
At first glance, interfacing with the shell may seem intimidating. A blank screen with only text can be daunting for many, but this should soon subside once you realize that you are basically in the folder explorer of your distro. To confirm where you are at, type in pwd
(short for print working directory). Hitting Enter
after typing the command in will return the path of your directory, or the list of parent folders for the folder you are currently in. For example, if I were using the file browser and I went to the top-most or root (/) directory, and then went to look for my home folder, the list of successive folders from root to the home folder in the browser could look something like this:
Here you can see that the home
folder is expanded and my user folder kchristm
is visible. When in the terminal if I type in pwd
right after opening the terminal, the folder I should be in by default is my home directory. The output of my command is:
❯ pwd
/home/kchristm
Pretty straightforward, no?
Checking folder contents
But simply knowing where you are in the file system isn’t super useful all by itself. After all, directories (or folders) are just containers. It’s what’s in them that is more interesting to us. To see the contents of a directory, we will type in ls
which will list the folder’s contents:
❯ ls
7_Segment_Array_Display_Clock.ino formatTime.py powerlevel10k
apps hillcrest_elementary.csv Public
Desktop lindon_pioneer_ln.csv seven_seg.png
dev Music snap
Documents oak_hills.csv Templates
Downloads orem_firehouse.csv thonny-latest.sh
EAGLE out.txt Videos
edgemont.csv pico
env Pictures
This is where the shell starts to become interesting. ls
(much like pwd
) is a command, and each command has flags or special options that come after a hyphen which allow for some special functionalities. Lets go ahead and use the l
flag after ls
and see what it does:
❯ ls -l
total 180784
-rw-rw-r-- 1 kchristm kchristm 20499 Jun 2 13:52 7_Segment_Array_Display_Clock.ino
drwxrwxr-x 3 kchristm kchristm 4096 May 28 13:08 apps
drwxr-xr-x 2 kchristm kchristm 4096 May 28 13:08 Desktop
drwxrwxr-x 8 kchristm kchristm 4096 May 28 10:23 dev
drwxr-xr-x 4 kchristm kchristm 4096 Jun 2 11:22 Documents
drwxr-xr-x 4 kchristm kchristm 4096 May 26 08:37 Downloads
drwxrwxr-x 10 kchristm kchristm 4096 May 26 08:58 EAGLE
-rw-rw-r-- 1 kchristm kchristm 28478118 May 25 13:21 edgemont.csv
drwxrwxr-x 3 kchristm kchristm 4096 May 18 12:16 env
-rw-rw-r-- 1 kchristm kchristm 518 May 25 13:20 formatTime.py
-rw-rw-r-- 1 kchristm kchristm 35316584 May 25 13:15 hillcrest_elementary.csv
-rw-rw-r-- 1 kchristm kchristm 33929904 May 25 13:15 lindon_pioneer_ln.csv
drwxr-xr-x 2 kchristm kchristm 4096 May 17 16:23 Music
-rw-rw-r-- 1 kchristm kchristm 29502077 May 25 13:16 oak_hills.csv
-rw-rw-r-- 1 kchristm kchristm 31997247 May 25 13:16 orem_firehouse.csv
-rw-rw-r-- 1 kchristm kchristm 25575881 Mar 9 23:22 out.txt
drwxrwxr-x 4 kchristm kchristm 4096 May 28 12:55 pico
drwxr-xr-x 3 kchristm kchristm 4096 May 25 12:53 Pictures
drwxr-xr-x 6 kchristm kchristm 4096 May 17 18:01 powerlevel10k
drwxr-xr-x 2 kchristm kchristm 4096 May 17 16:23 Public
-rw-rw-r-- 1 kchristm kchristm 214841 May 26 09:00 seven_seg.png
drwxr-xr-x 4 kchristm kchristm 4096 May 25 15:50 snap
drwxr-xr-x 2 kchristm kchristm 4096 May 17 16:23 Templates
-rwxrwxr-x 1 kchristm kchristm 763 May 23 02:22 thonny-latest.sh
drwxr-xr-x 2 kchristm kchristm 4096 May 17 16:23 Videos
As you can see, I have practically the same output. It’s still just the contents of my working directory. But as you have probably noticed, they have been displayed in a list. Other interesting bits of information such as the permissions of each file or folder, to whom its belongs and their corresponding group, and other metadata is displayed as well.
Flags can also be compounded together. For example, in ls
, the a
flag shows all the files in a directory (including the hidden files). Now when I type in ls -la
, I will see all the files in a list format:
❯ ls -la
total 181104
drwxr-xr-x 31 kchristm kchristm 4096 Jun 2 16:02 .
drwxr-xr-x 4 root root 4096 May 17 16:14 ..
-rw-rw-r-- 1 kchristm kchristm 20499 Jun 2 13:52 7_Segment_Array_Display_Clock.ino
drwxrwxr-x 3 kchristm kchristm 4096 May 28 13:08 apps
-rw------- 1 kchristm kchristm 314 Jun 2 11:22 .bash_history
-rw-r--r-- 1 kchristm kchristm 220 May 17 16:14 .bash_logout
-rw-r--r-- 1 kchristm kchristm 3771 May 17 16:14 .bashrc
drwxr-xr-x 22 kchristm kchristm 4096 Jun 2 15:53 .cache
drwxr-xr-x 26 kchristm kchristm 4096 May 28 11:43 .config
drwxrwxr-x 2 kchristm kchristm 4096 May 25 15:51 .dart
drwxrwxr-x 4 kchristm kchristm 4096 May 25 15:51 .dartServer
drwxr-xr-x 2 kchristm kchristm 4096 May 28 13:08 Desktop
drwxrwxr-x 8 kchristm kchristm 4096 May 28 10:23 dev
drwxr-xr-x 4 kchristm kchristm 4096 Jun 2 11:22 Documents
drwxr-xr-x 4 kchristm kchristm 4096 May 26 08:37 Downloads
drwxrwxr-x 10 kchristm kchristm 4096 May 26 08:58 EAGLE
-rw-rw-r-- 1 kchristm kchristm 28478118 May 25 13:21 edgemont.csv
drwxrwxr-x 3 kchristm kchristm 4096 May 18 12:16 env
-rw-rw-r-- 1 kchristm kchristm 78 May 25 15:51 .flutter
-rw-rw-r-- 1 kchristm kchristm 518 May 25 13:20 formatTime.py
-rw-rw-r-- 1 kchristm kchristm 56 May 20 10:05 .gitconfig
drwx------ 3 kchristm kchristm 4096 May 28 13:14 .gnupg
-rw-rw-r-- 1 kchristm kchristm 35316584 May 25 13:15 hillcrest_elementary.csv
-rw-rw-r-- 1 kchristm kchristm 33929904 May 25 13:15 lindon_pioneer_ln.csv
drwxr-xr-x 5 kchristm kchristm 4096 May 25 11:55 .local
-rw-rw-r-- 1 kchristm kchristm 85 May 25 09:57 .~lock.out.csv#
drwx------ 5 kchristm kchristm 4096 May 17 16:24 .mozilla
drwxrwxr-x 2 kchristm kchristm 4096 May 20 11:57 .mume
drwxr-xr-x 2 kchristm kchristm 4096 May 17 16:23 Music
-rw-rw-r-- 1 kchristm kchristm 29502077 May 25 13:16 oak_hills.csv
drwxr-xr-x 12 kchristm kchristm 4096 May 17 18:00 .oh-my-zsh
-rw-rw-r-- 1 kchristm kchristm 31997247 May 25 13:16 orem_firehouse.csv
-rw-rw-r-- 1 kchristm kchristm 25575881 Mar 9 23:22 out.txt
-rw-r--r-- 1 kchristm kchristm 88528 May 17 18:02 .p10k.zsh
drwxrwxr-x 4 kchristm kchristm 4096 May 28 12:55 pico
drwxr-xr-x 3 kchristm kchristm 4096 May 25 12:53 Pictures
drwx------ 3 kchristm kchristm 4096 May 17 16:51 .pki
drwxr-xr-x 6 kchristm kchristm 4096 May 17 18:01 powerlevel10k
-rw-r--r-- 1 kchristm kchristm 807 May 17 16:14 .profile
drwxrwxr-x 6 kchristm kchristm 4096 May 25 15:51 .pub-cache
drwxr-xr-x 2 kchristm kchristm 4096 May 17 16:23 Public
-rw-rw-r-- 1 kchristm kchristm 214841 May 26 09:00 seven_seg.png
-rw-r--r-- 1 kchristm kchristm 10 May 17 18:00 .shell.pre-oh-my-zsh
drwxr-xr-x 4 kchristm kchristm 4096 May 25 15:50 snap
drwx------ 2 kchristm kchristm 4096 May 25 09:38 .ssh
-rw-r--r-- 1 kchristm kchristm 0 May 17 16:56 .sudo_as_admin_successful
drwxr-xr-x 2 kchristm kchristm 4096 May 17 16:23 Templates
-rwxrwxr-x 1 kchristm kchristm 763 May 23 02:22 thonny-latest.sh
drwxr-xr-x 2 kchristm kchristm 4096 May 17 16:23 Videos
drwxrwxr-x 3 kchristm kchristm 4096 May 17 16:53 .vscode
-rw-rw-r-- 1 kchristm kchristm 227 May 28 13:07 .wget-hsts
drwx------ 2 kchristm kchristm 4096 May 25 15:42 .xournal
-rw-r--r-- 1 kchristm kchristm 49285 May 17 18:00 .zcompdump
-rw-rw-r-- 1 kchristm kchristm 50614 Jun 2 11:20 .zcompdump-EB228-EE10901-5.8
-rw------- 1 kchristm kchristm 14366 Jun 2 16:02 .zsh_history
-rw-r--r-- 1 kchristm kchristm 4256 May 17 18:02 .zshrc
-rw-rw-r-- 1 kchristm kchristm 94 May 17 17:59 .zshrc.pre-oh-my-zsh
As you can tell, there are many more files compared to our last command, and all the new ones are prepended with a .
to denote they are hidden. To be able to see hidden files in the GUI explorer, you would need to go into some sort of submenu to toggle the hidden file visibility whereas here we added just another letter to our command. Immediately, we can begin to see some advantages to using the shell.
Moving Around
Now that we can believe the shell actually represents our file system, or structure in which all of our files are organized on the computer, we should probably know how to actually move between files, or change directories cd
. In order to get into the dev
directory from my home directory, its as simple as typing in cd
and the name of the folder:
❯ cd dev
Once we hit enter, you may not notice any change in output, but just to prove that we actually moved into our folder, we can use either pwd
to verify our working directory or ls
to list the contents inside the current folder.
❯ cd dev
❯ ls
christopolise.github.io pico_stuff pm_world_clock pm_world_clock_client sensor_health_analyzer ssdd
In order to get back to our previous or parent directory, just use the ..
folder to get back. What’s ..
? If you noticed when we used ls -la
to see all the hidden files with our visible files, you’ll note that the first two files to show are .
and ..
. .
refers to the current or working directory. If we were to type in cd .
nothing would happen seeing as you are moving to the place where you already exist:
❯ pwd
/home/kchristm/dev
❯ cd .
❯ pwd
/home/kchristm/dev
..
on the other hand, refers to the parent directory, or the one right above. So if we use cd ..
, we should be able go back to our previous directory:
❯ pwd
/home/kchristm/dev
❯ cd ..
❯ pwd
/home/kchristm
You are well on your way to moving around in the shell!
Handling Files and Directories
Just as there are navigational commands which are analogues for actions in a normal file browser, there also exists such commands for actions such as renaming/moving, copying/pasting, and creating/removing files. Lets do a quick rapid-fire:
Renaming/Moving
Although they might not seem super related, renaming files and moving files are handled by the same command. To move something, we will use the mv
command and some arguments to the command. An argument is a required field after a command, for mv
, the most basic argument configuration is mv <target file> <target directory>
where the target file is the file to be moved and the target directory is where you want to put the file.
❯ ls
7_Segment_Array_Display_Clock.ino formatTime.py Pictures
apps gestures_MM.img powerlevel10k
Desktop hillcrest_elementary.csv Public
dev lindon_pioneer_ln.csv seven_seg.png
Documents Music snap
Downloads oak_hills.csv Templates
EAGLE orem_firehouse.csv thonny-latest.sh
edgemont.csv **out.txt** Videos
env pico
❯ mv out.txt dev
❯ cd dev
❯ ls
christopolise.github.io pico_stuff pm_world_clock_client ssdd
**out.txt** pm_world_clock sensor_health_analyzer
In order to rename a file, we will mv
the file to a new name instead of a new directory:
❯ ls
christopolise.github.io pico_stuff pm_world_clock_client ssdd
**out.txt** pm_world_clock sensor_health_analyzer
❯ mv out.txt banana.txt
❯ ls
**banana.txt** pico_stuff pm_world_clock_client ssdd
christopolise.github.io pm_world_clock sensor_health_analyzer
Copying/Pasting
Copying and pasting in the terminal is one action as opposed to its GUI counter part. To copy we will use the cp
command with the arguments of the source file and the output file.
❯ cp banana.txt banana2.txt
❯ ls
**banana2.txt** pico_stuff sensor_health_analyzer
**banana.txt** pm_world_clock ssdd
christopolise.github.io pm_world_clock_client
To copy whole folders with contents inside, follow the cp -r <source folder> <target directory>
Creating/Removing
To make a new directory we use the mkdir
command with the argument being the name of the new folder.
❯ mkdir test
❯ ls
banana2.txt pico_stuff sensor_health_analyzer
banana.txt pm_world_clock ssdd
christopolise.github.io pm_world_clock_client **test**
To make a new file, we will use the touch
command:
❯ touch newfile
❯ ls
banana2.txt **newfile** pm_world_clock_client test
banana.txt pico_stuff sensor_health_analyzer
christopolise.github.io pm_world_clock ssdd
Notice how I didn’t include an extension after the file. In Linux, files are extension-agnostic, meaning I can give it whatever extension I want, but file will still behave based on its composition. This means a text file with a PNG extension will not be a picture and a picture with a TXT file will not be a text document.
To remove files or directories, we use the rm
command. A specific rmdir
command exists only to work for directories, but rm
works for both, however, an r
flag is needed if the directory is not empty:
❯ ls
banana2.txt **newfile** pm_world_clock_client test
banana.txt pico_stuff sensor_health_analyzer
christopolise.github.io pm_world_clock ssdd
❯ rm newfile
❯ ls
banana2.txt pico_stuff sensor_health_analyzer
banana.txt pm_world_clock ssdd
christopolise.github.io pm_world_clock_client test
Running Programs and Commands
Running programs and opening files in the shell is about as straightforward as everything you have seen up until now. You have also probably gathered that each action you could normally do outside of the shell with your mouse has its own correlating command or low level program that executes the same function. So what available commands exist inside of the operating system? Well, technically there are several directories that you could look through such as /usr/bin
or the other directories that are shown between colons when you run echo $PATH
:
❯ echo $PATH
/home/kchristm/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
❯ cd /usr/bin
❯ ls
'[' debconf-escape gjs-console lastlog ntfsusermap rst2man unexpand
2to3-2.7 debconf-set-selections gkbd-keyboard-display lavadecode ntfswipe rst2odt unicode_start
aa-enabled debconf-show glib-compile-schemas lcf numfmt rst2odt_prepstyles unicode_stop
aa-exec debian-distro-info gnome-calculator ld nvidia-detector rst2pseudoxml uniq
aconnect deb-systemd-helper gnome-calendar ld.bfd oakdecode rst2s5 unity-scope-loader
acpi_listen deb-systemd-invoke gnome-characters ldd obexctl rst2xetex unlink
add-apt-repository deja-dup gnome-control-center ld.gold objcopy rst2xml unlz4
addpart delpart gnome-disk-image-mounter less objdump rstart unlzma
addr2line delv gnome-disks lessecho oclock rstartd unmkinitramfs
alsabat desktop-file-edit gnome-extensions lessfile od rst-buildhtml unopkg
alsaloop desktop-file-install gnome-extensions-app lesskey oem-getlogs rstpep2html unshare
alsamixer desktop-file-validate gnome-font-viewer lesspipe on_ac_power rsync unsquashfs
alsatplg devdump gnome-help lexgrog openssl rtstat unxz
alsaucm df gnome-keyring libnetcfg openvt runcon unzip
amidi dfu-tool gnome-keyring-3 libreoffice opldecode run-mailcap unzipsfx
amixer dh_bash-completion gnome-keyring-daemon libwacom-list-local-devices orca run-parts update-alternatives
amuFormat.sh dh_installxmlcatalogs gnome-language-selector link orca-dm-wrapper run-with-aspell update-desktop-database
apg dh_perl_openssl gnome-logs linkicc os-prober rview update-manager
apgbfm dh_python2 gnome-power-statistics linux32 p11-kit rygel update-mime-database
aplay diff gnome-screenshot linux64 pacat rzsh update-notifier
aplaymidi diff3 gnome-session linux-boot-prober pacmd sane-find-scanner upower
apport-bug dig gnome-session-custom-session linux-check-removal pactl savelog uptime
apport-cli dir gnome-session-inhibit linux-update-symlinks padsp sbattach usb-creator-gtk
apport-collect dircolors gnome-session-properties linux-version pager sbkeysync usb-devices
apport-unpack dirmngr gnome-session-quit listres pa-info sbsiglist usbhid-dump
appres dirmngr-client gnome-session-remmina ln pamon sbsign usb_printerid
appstreamcli dirname gnome-shell lnstat paperconf sbvarsign usbreset
apropos dirsplit gnome-shell-extension-prefs loadkeys paplay sbverify users
apt distro-info gnome-shell-extension-tool loadunimap parec scanimage utmpdump
apt-add-repository dmesg gnome-shell-perf-tool localc parecord scp uuidgen
apt-cache dmypy gnome-system-monitor locale partx scp-dbus-service uuidparse
apt-cdrom dnsdomainname gnome-terminal locale-check passwd screendump uz
apt-config domainname gnome-terminal.real localectl paste script vdir
aptdcon do-release-upgrade gnome-terminal.wrapper localedef pasteurize scriptreplay vi
apt-extracttemplates dpkg gnome-text-editor lodraw pasuspender sdiff view
apt-ftparchive dpkg-architecture gnome-thumbnail-font loffice patch sdptool viewres
apt-get dpkg-buildflags gnome-todo lofromtemplate pathchk seahorse vim.tiny
apt-key dpkg-buildpackage gnome-tweaks logger pax11publish sed virtualenv
apt-mark dpkg-checkbuilddeps gnome-www-browser logilab-pytest pdb2 see vmstat
apt-sortpkgs dpkg-deb gold login pdb2.7 select-default-iwrap vmwarectrl
apturl dpkg-distaddfile google-chrome loginctl pdb3 select-editor volname
apturl-gtk dpkg-divert google-chrome-stable logname pdb3.8 sensible-browser vstp
ar dpkg-genbuildinfo gpasswd loimpress pdf2dsc sensible-editor w
arch dpkg-genchanges gpg lomath pdf2ps sensible-pager wall
arecord dpkg-gencontrol gpg-agent look pdfattach seq watch
arecordmidi dpkg-gensymbols gpgcompose lorder pdfdetach session-migration watchgnupg
arm2hpdl dpkg-maintscript-helper gpgconf loweb pdffonts sessreg wc
arm-none-eabi-addr2line dpkg-mergechangelogs gpg-connect-agent lowntfs-3g pdfimages setarch wdctl
arm-none-eabi-ar dpkg-name gpgparsemail lowriter pdfinfo setfacl wget
arm-none-eabi-as dpkg-parsechangelog gpgsm lp pdfseparate setfont whatis
arm-none-eabi-c++ dpkg-query gpgsplit lpoptions pdfsig setkeycodes whereis
arm-none-eabi-c++filt dpkg-scanpackages gpgtar lpq pdftocairo setleds which
arm-none-eabi-cpp dpkg-scansources gpgv lpr pdftohtml setlogcons whiptail
arm-none-eabi-elfedit dpkg-shlibdeps gpg-wks-server lprm pdftoppm setmetamode who
arm-none-eabi-g++ dpkg-source gpg-zip lp_solve pdftops setpci whoami
arm-none-eabi-gcc dpkg-split gpic lpstat pdftotext setpriv whoopsie
arm-none-eabi-gcc-9.2.1 dpkg-statoverride gprof ls pdfunite setsid whoopsie-preferences
arm-none-eabi-gcc-ar dpkg-trigger gpu-manager lsattr peekfd setterm word-list-compress
arm-none-eabi-gcc-nm dpkg-vendor grep lsblk perl setupcon wpa_passphrase
arm-none-eabi-gcc-ranlib driverless gresource lsb_release perl5.30.0 setxkbmap w.procps
arm-none-eabi-gcov du groff lscpu perl5.30-x86_64-linux-gnu sftp write
arm-none-eabi-gcov-dump dumpkeys grog lshw perlbug sg X
arm-none-eabi-gcov-tool duplicity grops lsinitramfs perldoc sh X11
arm-none-eabi-gprof dvipdf grotty lsipc perli11ndoc sha1sum x11perf
arm-none-eabi-ld dwp groups lslocks perlivp sha224sum x11perfcomp
arm-none-eabi-ld.bfd echo grub-editenv lslogins perlthanks sha256sum x86_64
arm-none-eabi-nm ed grub-file lsmem pf2afm sha384sum x86_64-linux-gnu-addr2line
arm-none-eabi-objcopy edit grub-fstest lsmod pfbtopfa sha512sum x86_64-linux-gnu-ar
arm-none-eabi-objdump editor grub-glue-efi lsns pftp shasum x86_64-linux-gnu-as
arm-none-eabi-ranlib editres grub-kbdcomp lsof pgrep shotwell x86_64-linux-gnu-c++filt
arm-none-eabi-readelf efibootdump grub-menulst2cfg lspci pic showconsolefont x86_64-linux-gnu-cpp
arm-none-eabi-size efibootmgr grub-mkfont lspgpot pico showkey x86_64-linux-gnu-cpp-9
arm-none-eabi-strings egrep grub-mkimage lsusb piconv showrgb x86_64-linux-gnu-dwp
arm-none-eabi-strip eject grub-mklayout ltrace pidof shred x86_64-linux-gnu-elfedit
as elfedit grub-mknetdir luit pinentry shuf x86_64-linux-gnu-g++
aseqdump enc2xs grub-mkpasswd-pbkdf2 lwp-download pinentry-curses simple-scan x86_64-linux-gnu-g++-9
aseqnet encguess grub-mkrelpath lwp-dump pinentry-gnome3 size x86_64-linux-gnu-gcc
aspell enchant-2 grub-mkrescue lwp-mirror pinentry-x11 skill x86_64-linux-gnu-gcc-9
aspell-import enchant-lsmod-2 grub-mkstandalone lwp-request ping slabtop x86_64-linux-gnu-gcc-ar
atobm env grub-mount lz ping4 slack x86_64-linux-gnu-gcc-ar-9
avahi-browse envsubst grub-ntldr-img lz4 ping6 sleep x86_64-linux-gnu-gcc-nm
avahi-browse-domains eog grub-render-label lz4c pinky slogin x86_64-linux-gnu-gcc-nm-9
avahi-publish eps2eps grub-script-check lz4cat pip slxdecode x86_64-linux-gnu-gcc-ranlib
avahi-publish-address epylint grub-syslinux2cfg lzcat pip3 smproxy x86_64-linux-gnu-gcc-ranlib-9
avahi-publish-service eqn gs lzcmp pkaction snap x86_64-linux-gnu-gcov
avahi-resolve esc-m gsbj lzdiff pkcheck snapctl x86_64-linux-gnu-gcov-9
avahi-resolve-address eutp gsdj lzegrep pkcon snapfuse x86_64-linux-gnu-gcov-dump
avahi-resolve-host-name evince gsdj500 lzfgrep pkexec snice x86_64-linux-gnu-gcov-dump-9
avahi-set-host-name evince-previewer gsettings lzgrep pkg-config soelim x86_64-linux-gnu-gcov-tool
awk evince-thumbnailer gslj lzless pkill soffice x86_64-linux-gnu-gcov-tool-9
axfer ex gslp lzma pkmon software-properties-gtk x86_64-linux-gnu-gold
b2sum expand gsnd lzmainfo pkttyagent sort x86_64-linux-gnu-gprof
baobab expiry gst-device-monitor-1.0 lzmore pl2pm sotruss x86_64-linux-gnu-ld
base32 expr gst-discoverer-1.0 m2300w pldd spd-conf x86_64-linux-gnu-ld.bfd
base64 factor gst-inspect-1.0 m2300w-wrapper plog spd-say x86_64-linux-gnu-ld.gold
basename faillog gst-launch-1.0 m2400w plymouth speaker-test x86_64-linux-gnu-nm
bash faked-sysv gst-play-1.0 make pmap speech-dispatcher x86_64-linux-gnu-objcopy
bashbug faked-tcp gstreamer-codec-install make-first-existing-target pnm2ppa spice-vdagent x86_64-linux-gnu-objdump
bc fakeroot gst-typefind-1.0 mako-render pod2html splain x86_64-linux-gnu-pkg-config
bccmd fakeroot-sysv gtbl man pod2man split x86_64-linux-gnu-python2.7-config
bdftopcf fakeroot-tcp gtf mandb pod2text splitfont x86_64-linux-gnu-python2-config
bdftruncate fallocate gtk-builder-tool manpath pod2usage spotify x86_64-linux-gnu-python3.8-config
bitmap false gtk-encode-symbolic-svg man-recode podchecker sprof x86_64-linux-gnu-python3-config
bluemoon fc-cache gtk-launch mapscrn podselect ss x86_64-linux-gnu-ranlib
bluetoothctl fc-cat gtk-query-settings mattrib poff ssh x86_64-linux-gnu-readelf
bluetooth-sendto fc-conflist gtk-update-icon-cache mawk pon ssh-add x86_64-linux-gnu-size
bmtoa fc-list gunzip mbadblocks POST ssh-agent x86_64-linux-gnu-strings
boltctl fc-match gvfs-cat mcat ppdc ssh-argv0 x86_64-linux-gnu-strip
bootctl fc-pattern gvfs-copy mcd ppdhtml ssh-copy-id x86_64-pc-linux-gnu-pkg-config
brltty fc-query gvfs-info mcheck ppdi ssh-import-id xargs
brltty-ctb fc-scan gvfs-less mclasserase ppdmerge ssh-import-id-gh xauth
brltty-trtxt fc-validate gvfs-ls mcomp ppdpo ssh-import-id-lp xbiff
brltty-ttb fgconsole gvfs-mime mcookie pphs ssh-keygen xbrlapi
broadwayd fgrep gvfs-mkdir mcopy pr ssh-keyscan xcalc
browse file gvfs-monitor-dir md5sum precat start-pulseaudio-x11 xclipboard
bsd-from file2brl gvfs-monitor-file md5sum.textutils preconv startx xclock
bsd-write file-roller gvfs-mount mdel preunzip stat xcmsdb
btattach fincore gvfs-move mdeltree prezip static-sh xconsole
btmgmt find gvfs-open mdig prezip-bin stdbuf xcursorgen
btmon findmnt gvfs-rename mdir print strace xcutsel
bunzip2 firefox gvfs-rm mdu printafm strace-log-merge xdg-dbus-proxy
busctl fish gvfs-save mesa-overlay-control.py printenv strings xdg-desktop-icon
busybox fish_indent gvfs-set-attribute mesg printerbanner strip xdg-desktop-menu
bwrap fish_key_reader gvfs-trash mformat printer-profile stty xdg-email
bzcat flock gvfs-tree migrate-pubring-from-classic-gpg printf stubgen xdg-icon-resource
bzcmp fmt gzexe mimeopen prlimit su xdg-mime
bzdiff fold gzip mimetype prove sudo xdg-open
bzegrep fonttosfnt h2ph min12xxw prtstat sudoedit xdg-screensaver
bzexe foo2ddst h2xs minfo ps sudoreplay xdg-settings
bzfgrep foo2ddst-wrapper hbpldecode miniterm ps2ascii sum xdg-user-dir
bzgrep foo2hbpl2 hciattach mkdir ps2epsi symcryptrun xdg-user-dirs-gtk-update
bzip2 foo2hbpl2-wrapper hciconfig mkfifo ps2pdf symilar xdg-user-dirs-update
bzip2recover foo2hiperc hcitool mkfontdir ps2pdf12 sync xditview
bzless foo2hiperc-wrapper hd mkfontscale ps2pdf13 syslinux xdpyinfo
bzmore foo2hp head mkisofs ps2pdf14 syslinux-legacy xdriinfo
c++ foo2hp2600-wrapper HEAD mkmanifest ps2pdfwr system-config-printer xedit
c89 foo2lava helpztags mk_modmap ps2ps system-config-printer-applet Xephyr
c89-gcc foo2lava-wrapper hex2hcd mknod ps2ps2 systemctl xev
c99 foo2oak hexdump mksquashfs ps2txt systemd xeyes
c99-gcc foo2oak-wrapper hipercdecode mktemp psfaddtable systemd-analyze xfd
cal foo2qpdl host mkzftree psfgettable systemd-ask-password xfontsel
calendar foo2qpdl-wrapper hostid mlabel psfstriptable systemd-cat xgamma
calibrate_ppa foo2slx hostname mmcli psfxtable systemd-cgls xgc
canberra-gtk-play foo2slx-wrapper hostnamectl mmd psicc systemd-cgtop xhost
cancel foo2xqx hp-align mmount pslog systemd-delta xinit
captoinfo foo2xqx-wrapper hp-check mmove pstree systemd-detect-virt xinput
cat foo2zjs hp-clean mokutil pstree.x11 systemd-escape xkbbell
catchsegv foo2zjs-icc2ps hp-colorcal monitor-sensor ptar systemd-hwdb xkbcomp
catman foo2zjs-pstops hp-config_usb_printer more ptardiff systemd-id128 xkbevd
cautious-launcher foo2zjs-wrapper hp-doctor mount ptargrep systemd-inhibit xkbprint
cc foomatic-rip hp-firmware mountpoint ptx systemd-machine-id-setup xkbvleds
cd-create-profile fprintd-delete hp-info mousetweaks pulseaudio systemd-mount xkbwatch
cd-fix-profile fprintd-enroll hp-levels mpartition pwd systemd-notify xkeystone
cd-iccdump fprintd-list hp-logcapture mrd pwdx systemd-path xkill
cd-it8 fprintd-verify hp-makeuri mren py3clean systemd-resolve xload
c++filt free hp-pkservice mscompress py3compile systemd-run xlogo
chacl from hp-plugin msexpand py3versions systemd-socket-activate xlsatoms
chage ftp hp-plugin-ubuntu mshortname pyclean systemd-stdio-bridge xlsclients
chardet3 funzip hp-probe mshowfat pycompile systemd-sysusers xlsfonts
chardetect3 fuser hp-query mt pydoc systemd-tmpfiles xmag
chattr fusermount hp-scan mt-gnu pydoc2 systemd-tty-ask-password-agent xman
chcon futurize hp-setup mtools pydoc2.7 systemd-umount xmessage
check-language-support fwupdagent hp-testpage mtoolstest pydoc3 tabs xmodmap
cheese fwupdate hp-timedate mtr pydoc3.8 tac xmore
chfn fwupdmgr htop mtrace pygettext2 tail Xorg
chgrp fwupdtool hwe-support-status mtr-packet pygettext2.7 tar xournal
chmod fwupdtpmevlog i386 mtype pygettext3 taskset xprop
choom g++ i686-linux-gnu-pkg-config mutter pygettext3.8 tbl xqxdecode
chown g++-9 ibus mv pygmentize tee xrandr
chrome-gnome-shell gamemoded ibus-daemon mxtar pyjwt3 telnet xrdb
chrt gamemoderun ibus-setup mypy pylint telnet.netkit xrefresh
chsh gamma4scanimage ibus-table-createdb mzip pyreverse tempfile xsel
chvt gapplication iceauth namei python test x-session-manager
ciptool gatttool ico nano python2 tgz xset
ckbcomp gcalccmd iconv nautilus python2.7 thunderbird xsetmode
cksum gcc id nautilus-autorun-software python2.7-config tic xsetpointer
clear gcc-9 iecset nautilus-sendto python2-config tificc xsetroot
clear_console gcc-ar ijs_pxljr nawk python3 time xsetwacom
cmake gcc-ar-9 im-config nc python3.8 timedatectl xsm
cmp gcc-nm im-launch ncal python3.8-config timeout xstdcmap
code gcc-nm-9 info nc.openbsd python3-config tload xsubpp
codepage gcc-ranlib infobrowser ncurses5-config python3-futurize toe x-terminal-emulator
col gcc-ranlib-9 infocmp ncurses6-config python3-pasteurize top xvidtune
colcrt gcore infotocap ncursesw5-config python-config totem xvinfo
colormgr gcov inputattach ncursesw6-config pyvenv totem-video-thumbnailer Xwayland
colrm gcov-9 install neqn pyversions touch xwd
column gcov-dump install-info netcat qpdldecode tput x-window-manager
comm gcov-dump-9 install-printerdriver netkit-ftp quirks-handler tr xwininfo
compose gcov-tool instmodsh networkctl ranlib tracepath xwud
corelist gcov-tool-9 intel-virtual-output networkd-dispatcher rbash traceroute6 x-www-browser
cp gcr-viewer ionice newgrp rcp traceroute6.iputils xxd
cpack gdb ip ngettext rctest tracker xz
cpan gdb-add-index ipcmk nice rdiffdir transicc xzcat
cpan5.30-x86_64-linux-gnu gdbserver ipcrm nisdomainname rdma transmission-gtk xzcmp
cpio gdbtui ipcs nl readelf transset xzdiff
cpp gdbus ipod-read-sysinfo-extended nm readlink troff xzegrep
cpp-9 gdialog ipod-time-sync nm-applet realpath true xzfgrep
c_rehash gdk-pixbuf-csource ippfind nmcli red truncate xzgrep
crontab gdk-pixbuf-pixdata ipptool nm-connection-editor remmina trust xzless
csplit gdk-pixbuf-thumbnailer iptables-xml nm-online remmina-file-wrapper tset xzmore
ctest gdmflexiserver ischroot nmtui remmina-gnome tsort yelp
ctstat gdm-screenshot isdv4-serial-debugger nmtui-connect rename.ul ttfread yes
cupstestppd gedit isdv4-serial-inputattach nmtui-edit rendercheck tty ypdomainname
curl gencat isodump nmtui-hostname renice tzselect zcat
cut genisoimage isoinfo nohup reset ua zcmp
cvt geqn isovfy notify-send resizecons ubuntu-advantage zdiff
cvtsudoers GET ispell-wrapper nproc resizepart ubuntu-bug zdump
dash getconf join nroff resolvectl ubuntu-core-launcher zegrep
date geteltorito journalctl nsenter rev ubuntu-distro-info zenity
dbus-cleanup-sockets getent jpgicc nslookup rfcomm ubuntu-drivers zfgrep
dbus-daemon getfacl json_pp nstat rgrep ubuntu-report zforce
dbus-launch getkeycodes kbdinfo nsupdate rhythmbox ubuntu-security-status zgrep
dbus-monitor getopt kbd_mode ntfs-3g rhythmbox-client ucf zip
dbus-run-session gettext kbxutil ntfs-3g.probe rlogin ucfq zipcloak
dbus-send gettext.sh kernel-install ntfscat rm ucfr zipdetails
dbus-update-activation-environment ghostscript kerneloops-submit ntfscluster rmdir ucs2any zipgrep
dbus-uuidgen ginstall-info keyring ntfscmp rnano udevadm zipinfo
dc gio kill ntfsdecrypt routef udisksctl zipnote
dconf gio-querymodules killall ntfsfallocate routel ul zipsplit
dd gipddecode kmod ntfsfix rpcgen ulockmgr_server zjsdecode
ddstdecode git kmodsign ntfsinfo rrsync umax_pp zless
deallocvt git-receive-pack l2ping ntfsls rsh umount zmore
debconf git-shell l2test ntfsmove rst2html uname znew
debconf-apt-progress git-upload-archive laptop-detect ntfsrecover rst2html4 unattended-upgrade zsh
debconf-communicate git-upload-pack last ntfssecaudit rst2html5 unattended-upgrades zsh5
debconf-copydb gjs lastb ntfstruncate rst2latex uncompress
Sorry about that, I know the output is ridiculously long, but that is the point I am trying to make. There are so many commands, so trying to remember them all at this point is quite useless. Your best bet is to do a quick Google search and see which command is best for your use case. Sometimes you don’t even have the command available and will have to install it through your package manager, but that is a different topic for another article.
Manuals
There are so many flags for each command, how am I supposed to know what they do? Do I have to do a Google search each time? Maybe. But I would recommend trying to read the manual, before doing that. You can read the manual for the command by typing man <name of command>
and getting a nice overview of what it can do. For example, when trying to find all the different ways we can list the contents of our directory, just try man ls
:
❯ man ls
LS(1) User Commands LS(1)
NAME
ls - list directory contents
SYNOPSIS
ls [OPTION]... [FILE]...
DESCRIPTION
List information about the FILEs (the current directory by default). Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.
Mandatory arguments to long options are mandatory for short options too.
-a, --all
do not ignore entries starting with .
... (This goes on for a bit, to exit it, just hit q on your keyboard)
Opening Files
As mentioned before, Linux is extension-agnostic, but normally people are nice enough to leave them in anyways. To open text files, there are many different commands that you can use:
cat
cat
is a simple command that will spit out the contents of your file onto the terminal screen:
❯ cat test.txt
Hello, World!
However this can prove to be a little cumbersome when your files contain thousands of lines like banana.txt
:
❯ cat banana.txt
#datatype measurement,dateTime:RFC3339,double,double,double,double,double
loc,timestamp,PM1_0,PM2_5,PM10_0,temperature,humidity
orem_firehouse,2020-02-01T00:00:50Z,3.41,6,6.76,51,27
orem_firehouse,2020-02-01T00:02:50Z,3.07,5.65,6.16,51,26
orem_firehouse,2020-02-01T00:04:50Z,3.21,6.14,6.49,51,26
orem_firehouse,2020-02-01T00:06:50Z,3.99,6.14,7.48,50,26
orem_firehouse,2020-02-01T00:08:50Z,3.35,5.44,6.13,50,26
orem_firehouse,2020-02-01T00:10:50Z,3.39,6.02,6.59,50,27
orem_firehouse,2020-02-01T00:12:50Z,3.85,6.81,7.9,50,27
orem_firehouse,2020-02-01T00:14:50Z,4.3,6.72,7.61,51,27
orem_firehouse,2020-02-01T00:16:50Z,3.82,6.89,7.38,51,27
orem_firehouse,2020-02-01T00:18:50Z,3.64,6.17,6.67,51,27
... (literally continues for 50,000+ lines)
less
To fix this problem, we can use the less
command which will show the text in a scrollable screen where you can exit by pressing the q
key.
There are other alternatives to these commands and some will work better than others in certain situations, but this will be your job to figure it out when the time comes.
Running Programs
So lets say I have a program that is supposed to be executable from the folder because it is a shell script or a compiled program but is not in one of the directories shown in echo $PATH
, how am I supposed execute it? Well I am very glad you asked such a specific question 😉. The behavior of these programs will largely depend on the environment in which they run and the types of programs they are. If it is a program that is meant to be run through the terminal, executing it in the shell will cause the programs output to be placed on the terminal screen until the program’s execution is finished. However, if you are trying to run a graphical program, you should take the following into account:
- Am I running a headless instance? (When I turn the computer on, am I greeted by the shell and not a GUI)
- Am I connected to a remote shell? (Did I use
ssh
to connect to a remote computer?) - Am I using a terminal emulator inside of a desktop environment? (Did I click on a program that is called Terminal?)
If you are using one of the first two options, running a graphical program WILL NOT WORK (there is an x
flag that you can use for ssh
, but that is a different discussion for a different article.)
If you are using the last option, executing a graphical program will have some interesting advantages. You most likely will be able to see debug statements scroll across the terminal screen as the program runs in a separate window.
Regardless of which situation you find yourself in, executing a program is still the same across the board. ./
is prepended to the name of the executable you are trying to run. Alternatively, you can use sh
followed by the program in the folder or its path as the argument.
❯ ./test.sh
Hello World!
❯ sh test.sh
Hello World!
Permissions
Inevitably, when you try to run a program, you will encounter the dreaded error:
❯ ./test.sh
zsh: permission denied: ./test.sh
There are several routes you can take when you encounter this issue.
sudo
sudo
is the command you run when you want to execute a program as administrator, or to make the superuser do it. BE EXTREMELY CAREFUL WHEN DOING THIS!!! When you do something as superuser in a Linux system, there is no undoing this unless you have implemented your own fail-safe. You can RUIN your entire system if you are not careful.
The next option requires a little knowledge on how file permissions work. As this is an extensive topic that probably deserves an article of its own, I will suggest a quick fix and write another article if one is desired.
chmod
chmod
is a tool which allows you to edit the file permissions of any program which can be seen by executing ls -l
. You can refer to some of the links below to decipher what they mean, but what we need to do is add the argument +x
in order to add execution privileges.
❯ ./test.sh
zsh: permission denied: ./test.sh
❯ chmod +x test.sh
❯ ./test.sh
Hello World!
Conclusion
With this brief introduction, you are well on your way to breaking in that new distro of yours. Learning the shell may have a steep learning curve at first, but its effects are long lasting. The benefits come from the common struggle between perception and experience. A good user interface makes a system usable based on the user’s perception. Things such as double-clicking, windows, and countless specialized tools allow a person to intuit there way through a project, bringing a minimal amount of discomfort. Conversely, when the user chooses to embrace discomfort and use a less intuitive interface such as the shell, they will gain experience with a tool that will allow them to become the master of their system and gain much tangential understanding along the way.
Helpful Resources
File Permissions in Linux/Unix: How to Read/Write & Change?
(More to come as suggested, just leave a comment below!)