Introduction
UNIX is a family of multitasking, multiuser, time-sharing computer operating systems that derive from the original AT&T Unix, whose development started in 1969 at the Bell Labs research center mainly by Ken Thompson and Dennis Ritchie.
The most important UNIX families are:
- System V: like Oracle Solaris
- BSD 4.x: like FreeBSD, NetBSD, DragonFly BSD, …
- Linux with thousands of derivative distributions
Please, take a look at distro family tree image to see all the Linux distributions’ origins.
The UNIX key tools and architectures are:
- shell: command processor
- system language: C programming language
- system primitives
The virtual memory is an abstraction of physic RAM memory. A key aspect of UNIX is that the virtual memory is larger than the physic one, by means a process “think” to have unlimited memory while executing.
In UNIX, tasks are delegated to the process abstraction, which executes them by acceding to system virtual resources.
The file system represent the fundamental UNIX virtual machine.
Shortcuts
As a convention, inside all the shell snippets written on those blog posts, $
symbol (dollar sign) and a space will precede a command you could launch on your Terminal.
You must not write the $
and the space on your Terminal window, but what’s after it.
I’ll also write the output in the lines right below that command.
Here’s an example:
COMMAND
OUTPUT OF THE COMMAND
# my own comments about what's happening
Do not confuse COMMAND
with $COMMAND
, which is a variable named COMMAND
.
^KEY
means the key combination Ctrl
+ KEY
. So ^C
means Ctrl
+ C
, ^X
means Ctrl
+ X
and so on.
Here are some useful key combinations:
^C
stops the executing of a command in the Terminal^L
clears the screen and place the cursor back on top
You can also clear the console using a command:
clear
# same as ^L
In Linux, Ctrl
+ Alt
+ T
opens a Terminal window wherever you are and whatever you’re doing.
If you already have a Terminal window opened, Ctrl
+ Maiusc
+ T
opens a new tab.
To move between different Terminal tabs, use Ctrl
+ TAB
key.
Please Note: Maiusc
is the “up arrow” key, above Ctrl
key in almost all types of keyboards.
File System
Files are meant as byte sequences. In the file system there is a homogeneity between files and devices: everything is file.
The file system is structured as a tree where the root node is a directory called root
, often simply indicated as /
.
A file path can be expressed as:
- absolute: starting from the
root
folder - relative: starting from the current folder
The tree
command shows the tree structure of the current folder and all their sub-folders:
tree Desktop/
Desktop/
├── blog
│ └── index.html
├── fritzing.AppImage
├── homeworks
│ └── test.txt
├── Matlab.desktop
├── dog
│ └── subfolder
│ └── file.py
└── arduino-arduinoide.desktop
4 directories, 6 files
Let’s say we have the above structure inside Desktop
folder.
Taking, for example, test.txt
file:
# absolute path
/home/$USER/Desktop/homeworks/test.txt
# relative path from 'Desktop/blog'
../homeworks/test.txt
# relative path from 'Desktop/dog/subfolder'
../../homeworks/test.txt
Please Note: $USER
is a sort of placeholder for the current logged-in user (we’ll talk about it later on in this post).
Files & Directories Commands
If you want to know how a command (below indicated as COMMAND
) works and the options it needs, there are a couple of ways:
man COMMAND # 'man' stands for 'manual'
COMMAND --help # shows the help message, if implemented
present working directory
pwd
prints the name of the current working directory.
When you open a Terminal, pwd
should give /home/$USER
by default:
pwd
/home/pit
# my username is 'pit'
# echo $[VARIABLE-NAME] prints the variable
echo $USER
pit
change directory
cd
changes the shell working directory.
This example shows how the working directory has changed:
pwd # prints the 'present working directory'
/home/$USER
cd Desktop/ && pwd
/home/pit/Desktop
list directory
ls [OPTION]... [FILE]...
ls
lists information about files and directory in the present working directory (by default).
If you want to learn more about ls
command, please refer to ls command in UNIX.
Please Note: [OPTION]...
are the optional arguments of the command.
make directories
mkdir [OPTION]... DIRECTORY...
Create the DIRECTORY
(ies), if they do not already exist.
If you need to create the directory seaside
inside Documents
:
cd Documents/
mkdir seaside
If you need to create more directories:
mkdir bash-lang python-notes c-pp
remove directories
rmdir [OPTION]... DIRECTORY...
Delete the DIRECTORY
(ies), if they are empty.
If, for example, you need to remove the directory seaside
from Documents
, you could type:
cd Documents/
rmdir seaside
You can encounter a couple of problems.
rmdir seaside
# the repository does not exist
rmdir: failed to remove 'seaside': No such file or directory
# the directory is not empty
rmdir: failed to remove 'seaside': Directory not empty
copy
cp [OPTION]... SOURCE DEST
cp [OPTION]... SOURCE... DIRECTORY
Copy SOURCE
to DEST
, or multiple SOURCE
(s) to DIRECTORY
.
Let’s make an example:
cd Desktop/
# create a file
touch file-to-copy.txt
# check the content of 'blog' directory
ls blog/
index.html
# copy the file
cp file-to-copy.txt blog/
# check again the content of 'blog'
ls blog/
file-to-copy.txt index.html
link
# create a link to TARGET with the name LINK_NAME
ln [OPTION]... [-T] TARGET LINK_NAME
# create a link to TARGET in the current directory
ln [OPTION]... TARGET
# create links to each TARGET in DIRECTORY
ln [OPTION]... TARGET... DIRECTORY
ln [OPTION]... -t DIRECTORY TARGET...
If you want to learn more about ln
command, please refer to ln command in UNIX.
mv command
mv [OPTION]... [-T] SOURCE DEST
mv [OPTION]... SOURCE... DIRECTORY
mv [OPTION]... -t DIRECTORY SOURCE...
Rename SOURCE
to DEST
, or move SOURCE
(s) to DIRECTORY
.
remove files or directories
rm [OPTION]... [FILE]...
rm
removes each specified file. By default, it does not remove directories.
If you want to learn more about rm
command, please refer to rm command in UNIX.
visualize file
cat [OPTION]... [FILE]...
cat
concatenate files and print on the standard output.
terminal-based text editor
nano [options] [[+line[,column]] file]...
nano [options] [[+[crCR](/|?)string] file]...
nano
stands for Nano’s ANOther editor. It is an easy to use terminal-based text editor.
If you want to learn more about nano
editor, please refer to NANO Terminal Text Editor.
echo command
echo [SHORT-OPTION]... [STRING]...
echo LONG-OPTION
echo
is used in bash
scripting to print messages to the user.
Let’s take a look at the -e
option:
# -e enables interpretation of backslash escapes
echo Hello\\nWorld
Hello\nWorld
echo -e Hello\\nWorld
Hello
World
It can also be used to print environmental variables:
# print the list of environmental variables
printenv
SHELL=/bin/bash
HOME=/home/pit
# many others
# echo $VARIABLE_NAME prints the variable
echo $HOME
/home/pit
If you want to learn more about printenv
command, please refer to printenv command in UNIX.
Coding Convention: If you want to define your own variables while scripting, write their names in lowercase. As convention, uppercase names are reserved for environmental variables.
sort lines of text files
sort [OPTION]... [FILE]...
sort [OPTION]... --files0-from=F
Write sorted concatenation of all FILE
(s) to standard output.
With no FILE
(or when FILE
is -
), read standard input, just like nano
does.
If you want to learn more about sort
command, please refer to sort command in UNIX.
wc command
wc [OPTION]... [FILE]...
wc [OPTION]... --files0-from=F
wc
command prints newline, word and byte counts for each FILE
, and a total line if more than one FILE
is specified.
This command is often used with pipe operator together with previous commands.
If you want to learn more about wc
command, please refer to wc command in UNIX.
head & tail commands
head [OPTION]... [FILE]...
tail [OPTION]... [FILE]...
head
command prints the first 10 lines of each FILE
to standard output.
tail
command prints the last 10 lines of each FILE
to standard output.
They have very similar options:
-n NUM
: print the first/lastNUM
lines, instead of the first/last 10-c NUM
: print the first/lastNUM
bytes of eachFILE
Advanced Commands
Before reading the commands below, I really suggest you to read Processes in UNIX segment.
I had to place those commands here, but they require some topics like I/O redirection and piping, which are illustrated in the slices below.
cut command
cut OPTION... [FILE]...
It removes sections from each line of files.
In other word, it prints selected parts of lines from each FILE
to standard output.
If you want to learn more about cut
command, please refer to cut command in UNIX.
search for files in a directory hierarchy
find [-H] [-L] [-P] [-D debugopts] [-Olevel] [starting-point...] [expression]
GNU find
searches the directory tree rooted at each given starting-point.
It evaluates the given expression from left to right until the outcome is known, at which point find
moves on to the next file name.
If you want to learn more about find
command, please refer to find command in UNIX.
translate or delete characters
tr [OPTION]... SET1 [SET2]
Translate, squeeze, and/or delete characters from standard input, writing to standard output.
If you want to learn more about tr
command, please refer to tr command in UNIX.
wget command
wget [option]... [URL]...
GNU Wget
is a free utility for non-interactive download of files from the Web.
Here is a short example:
# '-P','--directory-prefix=PREFIX': save files to 'PREFIX/'.
wget -P Documents/ https://gitlab.com/-/snippets/2270320/raw/main/silvia.txt
# ...
2022-03-12 15:40:16 (2,35 MB/s) - ‘Documents/silvia.txt’ saved [452/452]
If you want to learn more about wget
command, please refer to wget command in UNIX.
tee command
tee [OPTION]... [FILE]...
tee
command copies standard input to each FILE
, and also to standard output.
It’s useful to monitor a stage of a pipe when writing commands with many pipes.
Given silvia.txt
, here is a short example:
cat silvia.txt | grep "help" | tee check-file.txt | tr [:lower:] [:upper:]
TO HELP HIM OF HIS BLINDNESS;
AND, BEING HELP'D, INHABITS THERE.
# check-file.txt contains the result of the first part of the command
cat check-file.txt
To help him of his blindness;
And, being help'd, inhabits there.
test command
test EXPRESSION
test
command checks file types and compare values.
If you want to learn more about test
command, please refer to test command in UNIX.
Wild Cards
Also named metacharacters or special characters. They allow the shell to execute pattern matching between a string and file names in the present working directory.
The symbol *
abbreviates any string of zero or more characters in a file name:
cd /dev && ls tty*
tty tty13 tty19 tty24 tty3 tty35 tty40 tty46 tty51 tty57 tty62 ttyS0 ttyS14 ttyS2 ttyS25 ttyS30 ttyS8
tty0 tty14 tty2 tty25 tty30 tty36 tty41 tty47 tty52 tty58 tty63 ttyS1 ttyS15 ttyS20 ttyS26 ttyS31 ttyS9
tty1 tty15 tty20 tty26 tty31 tty37 tty42 tty48 tty53 tty59 tty7 ttyS10 ttyS16 ttyS21 ttyS27 ttyS4
tty10 tty16 tty21 tty27 tty32 tty38 tty43 tty49 tty54 tty6 tty8 ttyS11 ttyS17 ttyS22 ttyS28 ttyS5
tty11 tty17 tty22 tty28 tty33 tty39 tty44 tty5 tty55 tty60 tty9 ttyS12 ttyS18 ttyS23 ttyS29 ttyS6
tty12 tty18 tty23 tty29 tty34 tty4 tty45 tty50 tty56 tty61 ttyprintk ttyS13 ttyS19 ttyS24 ttyS3 ttyS7
The symbol ?
abbreviates any character (a single one) in a file name:
cd /dev && ls i2c-?
i2c-0 i2c-1 i2c-2 i2c-3 i2c-4 i2c-5 i2c-6 i2c-7
[ccc...]
stands for any character in a file name, between the elements the square brackets.
[c-c...]
stands for any character in a file name, in all the elements between the extremes of the set(s) in the square brackets.
cd /dev/
# elements starts with 'tty', ends with '1', '5' or '8'
ls tty[158]
tty1 tty5 tty8
# elements starts with 'tty' and has '1', '5' or '8', then any string
ls tty[158]*
tty1 tty11 tty13 tty15 tty17 tty19 tty50 tty52 tty54 tty56 tty58 tty8
tty10 tty12 tty14 tty16 tty18 tty5 tty51 tty53 tty55 tty57 tty59
# elements starts with 'tty', ends with characters between '1' and '9' (included)
ls tty[1-9]
tty1 tty2 tty3 tty4 tty5 tty6 tty7 tty8 tty9
# some edge cases:
ls tty[14879]
tty1 tty4 tty7 tty8 tty9
ls tty[1-3-7-9]
tty1 tty2 tty3 tty7 tty8 tty9
# elements starts with 'tty' and than does not contains any numerical character
ls tty*[!0-9]
ttyprintk
The hash symbol #
comments until the end of the line (as you can see in almost all the examples).
The backslash (\
symbol) is the escape metacharacter: it tells bash not to interpret the subsequent character as a special character.
cd /dev/
# prints all the string that starts with 'loop' and ends with any string
echo loop*;
loop0 loop1 loop10 loop11 loop12 loop13 loop14 loop15 loop16 loop17 loop18 loop2 loop3 loop4 loop5 loop6 loop7 loop8 loop9 loop-control
# escaping '*' symbol
# this command gives the same result even if launched outside /dev/ directory
echo loop\*;
loop*
Please Note:
- Current directory is identified by the single dot (
.
symbol). - Parent directory of a given directory is identified by a couple of dots (
..
).
pwd . # prints the 'present working directory'
/home/$USER
pwd # you can omit the single dot
/home/$USER
cd Desktop/ && pwd
/home/pit/Desktop
cd .. && pwd
/home/$USER
Linux File System
Let’s take, for example, any Linux-based Operative System. It’s File System Hierarchy Standard is well-defined at pathname.com/fhs/.
As you can read in paragraph 3.2 Requirements of fhs-2.3.pd, the following directories (or symbolic links to directories) are required in /
(root
).
Directory | Description |
---|---|
bin | Essential command binaries |
boot | Static files of the boot loader |
dev | Device files |
etc | Host-specific system configuration |
lib | Essential shared libraries and kernel modules |
media | Mount point for removable media |
mnt | Mount point for mounting a filesystem temporarily |
opt | Add-on application software packages |
sbin | Essential system binaries |
srv | Data for services provided by this system |
tmp | Temporary files |
usr | Secondary hierarchy |
var | Variable data |
The root user
A multi-user system like UNIX must manage the access of different users to the physic machine and protect users’ files to one another. A user obliviously logs-in using a username and a password, like in all the modern infrastructures.
Moreover, a root user always exists on a UNIX machine. It is the so-called super-user since it is the system manager. It has no file limitations, and it’s not subject to the security rules of all others users.
You need root privileges to perform a variety of tasks on the OS, like installing packages or work with certain files.
If your current logged-in user is inside the sudo
group, he can act as root user by preceding the terminal commands with the word sudo
, which stands for Super-User DO.
Let’s open a Terminal and play it around a bit:
whoami # prints the logged-in user's name
pit
groups # prints group memberships for the current logged-in user
pit adm dialout cdrom sudo audio dip plugdev lpadmin lxd sambashare libvirt docker
apt update # let's try to update apt packages without sudo privileges
Reading package lists... Done
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
E: Unable to lock directory /var/lib/apt/lists/
W: Problem unlinking the file /var/cache/apt/pkgcache.bin - RemoveCaches (13: Permission denied)
W: Problem unlinking the file /var/cache/apt/srcpkgcache.bin - RemoveCaches (13: Permission denied)
Without sudo
privileges, the command above gives some Permission denied errors, which means my user is not allowed to perform that action.
Let’s run the command again by preceding it with the sudo
word:
sudo apt update # you'll be asked to insert your password
# [sudo] password for pit:
Hit:1 http://dl.google.com/linux/chrome/deb stable InRelease
Hit:2 http://it.archive.ubuntu.com/ubuntu focal InRelease
Get:3 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
# Hit:4, 5, 6, ... all the other packages
Fetched 1.156 kB in 4s (294 kB/s)
Reading package lists... Done
Building dependency tree
Reading state information... Done
3 packages can be upgraded. Run 'apt list --upgradable' to see them.
When prompting your password, it may happen that neither the usual *
are shown for safety reason: someone looking at you behind your shoulder will neither be able to determinate the length of your password.
Please Note: I’m using a Debian-based Linux distribution. The command apt update
could have no meaning in your OS and not work even with sudo privileges.
Users credentials
All users’ credentials of a UNIX machine are stored in /etc/passwd
system file. It is a sort of database of the registered users where are stored the following information separated by the :
(colon) symbol:
- username: the actual username’s name
- password: this field is set to
x
, encrypted passwords are stored in the/etc/shadow
file - UID: User IDentifier, number that uniquely identifies the user in the system
- GID: Group IDentifier, number that uniquely identifies the user’s group in the system
- comment: a comment field
- directory: absolute path to the user’s home directory. By default, it’s named after the name of the user and created under the
/home
directory - login shell: absolute path to the user’s login shell. This is the shell that is started when the user logs into the system
Let’s take a look at that file:
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
# many other lines
pit:x:1000:1000:Pietro Poluzzi,,,:/home/pit:/bin/bash
File protection
Since UNIX is a multi-user system, it must manage the access to files in order to guarantee the privacy for all users.
Foreach file, are defined three classes of users:
- owner: user that owns the file
- owner’s group: users which share the same group of the file owner
- others: all the others users
Foreach class of user, there are three ways to access the file:
- r: read
- w: write
- x: execute
Since every user is identified by the UID and GID, every file is marked with:
- owner’s UID and GID
- 12 permission bits
12 | 11 | 10 | 9 | 8 | 7 | 6 | … |
---|---|---|---|---|---|---|---|
SUID | SGID | sticky | r | w | x | … |
The nine bits on the right are three terns of read/write/execute permissions for the three classes of users defined above.
SUID stands for Set-User-IDentifier and is applied only to executable files.
If it’s set to 1
, the user which is executing that program is considered the file owner (only for the duration of the file execution).
The SUID bit is necessary to allow, during the file execution, read/write operations over system files that the user would not have the rights to read/write.
SGID stands for Set-Group-IDentifier bit works similar to SUID but for the group.
The sticky bit is used by the system to try to keep in memory the program image, even if it’s not executing.
chmod command
chmod [OPTION]... MODE[,MODE]... FILE...
chmod [OPTION]... OCTAL-MODE FILE...
chmod [OPTION]... --reference=RFILE FILE...
chmod
changes permissions to an element.
Let’s take dog
folder from Desktop
, create a file named hello-world.c
.
Create the executable and then ls
the directory:
cd Desktop/dog/
gcc -o hello-world hello-world.c
# create an executable file
./hello-world
Hello, World
ls -lha
total 36K
drwxrwxr-x 3 pit pit 4,0K mar 8 15:56 .
drwxr-xr-x 5 pit pit 4,0K mar 8 12:51 ..
-rwxrwxr-x 1 pit pit 17K mar 8 15:49 hello-world
-rwxr-xrw- 1 pit pit 98 mar 8 15:49 hello-world.c
drwxrwxr-x 2 pit pit 4,0K mar 7 15:29 subfolder
As you can see, both the owner and the owner’s group has read, write and execute permissions over hello-world
file; while other users only have read and execute permissions.
Nota that, in ls -l
command, the first string of each line contains:
- character to determinate the type of the item:
d
for a directory-
for a filel
for symlinkc
for character (a device that works with chars)b
for blocks (a device that works with blocks)
- permission bits from
9
to1
You can change the permission to files or directories using: chmod
, three terns of numbers (defined below) and the file(s)/directory(ies) path(s).
Take a look at this table:
number | permission |
---|---|
0 | --- |
1 | --x |
2 | -w- |
3 | -wx |
4 | r-- |
5 | r-x |
6 | rw- |
7 | rwx |
You need to combine the three terns to set the permissions for the three classes of users (owner, owner’s group and others) and three ways to access the file (read, write, execute).
If you want to change the permissions to hello-world
in order to deny you to execute the file, you need to do as follows:
chmod 665 hello-world
./hello-world
bash: ./hello-world: Permission denied
ls -lha
total 36K
drwxrwxr-x 3 pit pit 4,0K mar 8 15:56 .
drwxr-xr-x 5 pit pit 4,0K mar 8 12:51 ..
-rw-rw-r-x 1 pit pit 17K mar 8 15:49 hello-world
-rwxr-xrw- 1 pit pit 98 mar 8 15:49 hello-world.c
drwxrwxr-x 2 pit pit 4,0K mar 7 15:29 subfolder
As you see now, owner and owner’s group has only read and write permissions over hello-world
file.
The only user who can execute the file is root
.
Processes in UNIX
A process in a program which is executing on the system. Each process has its own address space, which is separated from the other processes’ address spaces.
Each process is uniquely identified by the PID (Process IDentifier): an integer number major than zero, assigned by the OS at the start of the process.
The shell
is the command interpreter: executes the given commands one by one.
loop forever
<accept command from console>
<execute command>
end loop;
shell
is a command processor that accept commands given from the terminal (or from a command file) and execute them until the file’s end.
I/O Redirection
UNIX commands acts as filters which operate line by line.
By default, all UNIX processes are linked to:
- stdin: standard input (keyboard)
- stdout: standard output (video)
- stderr: standard error (video)
It’s possible to redirect standard output (stdout) using >
sign:
# COMMAND > file-output
ls -F > ls-file.txt
cat ls-file.txt
arduino-arduinoide.desktop*
dog/
homeworks/
ls-file.txt
The >
sign will override the content of the output file: you can append to file using >>
sign.
# COMMAND >> file-output
ls >> ls-file.txt
It’s possible to redirect standard input (stdin) using <
sign:
# COMMAND < file-input
sort < ls-file.txt
arduino-arduinoide.desktop*
dog/
homeworks/
ls-file.txt
A comprehensive example:
sort < ls-file.txt > sorted-ls-file.txt
cat sorted-ls-file.txt
arduino-arduinoide.desktop*
dog/
homeworks/
ls-file.txt
UNIX processes can access files only by using file descriptors (integer numbers major than zero). This brings to the definition of the following file descriptors:
- Standard input:
0
- Standard output:
1
- Standard error:
2
# redirect standard output
# COMMAND 1> file-output
ls 1> ls-file.txt
# redirect standard error
# COMMAND 2> file-error
ls 2> ls-file.txt
# redirect both standard output and standard error
# COMMAND 2>&1 file-output-error
ls 2>&1 ls-file.txt
# redirect standard input
# COMMAND 0< file-input
ls 0< ls-file.txt
Moreover, you can find stdin, stdout and stderr in /dev/
directory:
cd /dev/
# with long listing format you find out they're soft links
ls -lha std*
lrwxrwxrwx 1 root root 15 mar 13 10:52 stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 mar 13 10:52 stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 mar 13 10:52 stdout -> /proc/self/fd/1
# which points to other soft links
cd /proc/self/fd/ && ls -lha
lrwx------ 1 pit pit 64 mar 14 00:05 0 -> /dev/pts/3
lrwx------ 1 pit pit 64 mar 14 00:05 1 -> /dev/pts/3
lrwx------ 1 pit pit 64 mar 14 00:05 2 -> /dev/pts/3
# ...
Since devices (in UNIX) are files, you can make a redirect to a device.
Let’s open a couple of Terminal windows (called T1
and T2
for simplicity).
# On T2, display information about a selection of
# the active processes on the system with 'ps a'
ps a
PID TTY STAT TIME COMMAND
1138 tty1 Ssl+ 2:02 /usr/lib/xorg/Xorg -nolisten tcp -auth
5744 pts/1 Ss+ 0:00 /bin/bash # T1
7303 pts/2 Ss 0:00 /bin/bash # T2
7333 pts/2 R+ 0:00 ps a
# On T1, redirect stdout of the file to T2
cat ls-file.txt > /dev/pts/2
Pipe
A pipe connects the output of a command to the input of another process. It uses the |
symbol.
Keep in mind that it creates a process foreach command.
COMMAND-1 | COMMAND-2
Let’s see it in action with our terminals T1
and T2
:
T1
launches a very long-running commandT2
launches looks for the processes launched byT1
# On T1 run the command with the pipe operator
# make a recursive ls and display the tree
ls -R | tree
# [...] lots of lines to display
# On T2, display information about active processes
ps a
PID TTY STAT TIME COMMAND
8812 pts/2 Ss 0:00 /bin/bash
8907 pts/3 Ss 0:00 /bin/bash
9943 pts/3 S+ 0:00 ls --color=auto -R
9944 pts/3 R+ 0:00 tree -R
9945 pts/2 R+ 0:00 ps a
As you can see above:
/bin/bash
processes:T1
is attached to/dev/pts/3
T2
is attached to/dev/pts/2
T2
runsps a
commandT1
runs:ls --color=auto -R
tree
# other examples
# count connected users (see 'man who')
who | wc -l
# display recursive 'ls' in a very readable way
ls -R | more
Execute shell commands
Built-in commands (like ls
, echo
, …) are executed by the current shell (the one that launched them).
Lots of commands are instead executed by a newly created shell, specifically designed for executing that command.
The active shell (father) puts in executing a second shell which:
- parsing: execute metacharacters and parameters substitution
- look for the command
- execute the command
The father shell waits for the finish of the second shell execution, then take back the control and allow the user to perform other commands.
Please Note: Commands are launched in foreground by default, means you do not have access to the shell until the previous command finishes.
You can launch shell commands in background using the &
symbol at the end of the command:
# COMMAND &
ls -R &
Parsing
Before executing, the command line is parsed to look after special characters. The very first parsed metacharacters are redirection and piping. In the subsequent scanning, if the shell find any other special character, result in one of the following substitutions:
- command: commands place among
“
(backquotes) are executed and the result is produced, - variable & parameters: variables’ names (
$VAR_NAME
) are substituted with their actual values, - file names:
*
,?
,[]
metacharacters are substituted into the file names using pattern matching
Execute the command pwd
, append /Desktop
and echo
the result.
echo `pwd`/Desktop
/home/pit/Desktop
Execute the command pwd
, append $desk
variable and ls
the result.
# create 'desk' variable
desk=/Desktop
echo $desk
/Desktop
ls -lha `pwd`$desk
total 95M
drwxr-xr-x 5 pit pit 4,0K mar 10 23:34 .
drwxr-xr-x 48 pit pit 4,0K mar 11 10:35 ..
-rwxr-xr-x 1 pit pit 364 ott 26 11:57 arduino-arduinoide.desktop
# ...
Execute the command pwd
, append $desk
variable, perform *
files’ names substitution and ls
the result.
ls `pwd`$desk/*
/home/pit/Desktop/arduino-arduinoide.desktop
/home/pit/Desktop/fritzing.AppImage
# ...
/home/pit/Desktop/blog:
file-to-copy.txt index.html
/home/pit/Desktop/dog:
hello-world hello-world.c subfolder
/home/pit/Desktop/homeworks:
test.txt
Moreover, the use of the quotes (single and double) allow and disallow certain types of substitutions.
Single quotes disallow all the substitution types:
# 1) command substitution
echo '`pwd`'
`pwd`
# 2) variable substitution
desk=/Desktop
echo '$desk'
$desk # this is the actual output line
# 3) file names substitution
echo 'Desktop/b*'
Desktop/b*
# without quotes would be
echo Desktop/b*
Desktop/blog
Double quotes only disallow file names substitutions:
# 1) command substitution
echo "`pwd`"
/home/pit
# 2) variable substitution
desk=/Desktop
echo "$desk"
/Desktop
# 3) file names substitution
echo "Desktop/b*"
Desktop/b*
Both single and double quotes disallow the shell to interpreter redirection and piping metacharacters.
eval command
eval
executes arguments as a shell command. It allows an additional phases of substitution.
my_command='ls|more'
echo $my_command
ls|more
$my_command
ls|more: command not found
eval $my_command
Arduino
Desktop
Documents
# ...
Quotes
Here are some useful links I used while writing this article: