The Unix Shell
The Shell is a program which uses command-line interface, instead
of graphical user interfaces (GUI), to run other programs rather than
doing calculations itself. The most popular Unix Shell is Bash which
is accessible by ctrl+alt+t
keyboard shortcut in Linux
computers. The following are some great Shell tutorials:
- The Unix Shell
- Extra Unix Shell Material
- Introduction to using the shell in a High-Performance Computing context
This tutorial provides a reference of some practical commands in the Unix Shell and important text editors in Bash.
Tab completion
In the Unix Shell we can use tab completion to
type commands faster and easier. To do that press tab
after typing the beginning of your command and let Bash complete the
command. If there are more than one function or directory corresponded
to the beginning that you typed, Bash will not return anything if your
press tab
once. In this case, if you press
tab
for the second time Bash will show all the
options.
Wildcards
A string is a wildcard pattern if it contains one of the characters
?
, *
or [
. Globbing is the
operation that expands a wildcard pattern into the list of pathnames
matching the pattern. For more information on globbing pathnames
typing man 7 glob
.
Matching:
- A
?
matches any single character. For example,hd?
would look forhda
,hdb
,hdc
and every other letter/number betweena-z
,0-9
- A
*
matches any string, including the empty string. For example,hd*
would look forhd
,hdf
,hd-full
, and anything that starts withhd
also includinghd
itself. Andm*l
could bymail
,mall
,ml
, and anything that starts with anm
and ends with anl
Character classes:
- An expression
[ ]
, where the first character after the leading[
is not an!
, matches any of the characters enclosed by the brackets. For example,m[a-d]m
can become anything that starts and ends withm
and has any charactera
tod
in between. - An expression
[! ]
, where the first character after the leading[
is an!
, matches any character that is not enclosed by the brackets.
Shell Expansions
- Brace expansion: is a mechanism by which arbitrary strings may be
generated for example
echo 1{2,3}4
returns 124 and 134 orecho {1..3}
returns 1,2, and 3 - Command substitution: it allows the output of a command to replace
the command itself for example,
echo $(date)
returns the actual date. Note that for the environmental variables you cannot use()
, for exampleecho $HOME
orecho ${HOME}
is the correct way
Basic commands
The following is a list of basic Bash commands. You may find a short explanation next to each command.
man <command> # user manual of the command (enter q to exit)
<command> --help # display brief help
uname # print operating system name
alias # show alias
env # show all environmental variables
w # show current users
hostnme # show the host nsme
whoami # show the user name
id # shows your id
passwd # change user password
nproc # show number of processors
lscpu # list CPU, display information about the CPU architecture
free -h # show amount of memory RAM
ps # report a snapshot of the current processes
file # determine file type
date # show date and time
pwd # print working directory
cd # change directory. Use cd .. or ~ or / to go back or home or system dir
ls # lists. Use flages -al to see all files in long formats
cp # copy a file. Use -r to copy a directory recursively
scp # secure copy a file. Use -r to copy a directory
sftp # secure file transfer program (SSH file transfer protocol)
wget # the non-interactive network downloader (-O <newname> to rename)
curl # copy a url. Use -o to name the output
md5sum # compute MD5 message digest. Use -c to check the digits
tar -c/xzf # to archive and create(c)/extract(x) a compressed(z) file(f)
ln # make links between files
mv # move
rm # remove file. Use -r to remove a directory
mkdir # make a directory
rmdir # remove an empty directory
install -dvp # make a directory(d), verbose(v) and parent(p)
cat # concatenate files and print on the standard output
zcat # concatenate compressed (zip) files
diff <file1> <file2> # compare files line by line. Use -y for side by side and -q for report only when files differ
less # to view the contents of a text file one screen at a time (less than a text editor)
touch # generate a new file that contains no data
chmod # change file mode for user(u), group(g) or other(o) to give(+) or take(-) permission for read(r), write(w), or execute(x) (example chmod u+r)
echo # display a line of text ex. echo === $(date)
cut -f <field number> -d <delimiter> # cut field number based on the delimiter
grep # print lines matching a pattern (global regular expression print)
sed # stream editor for filtering and transforming text
tr # translate or delete characters (for example 'tr -d ,' removes comma)
awk # pattern scanning and text processing language
wc # word count; it counts the number of lines(-l), words(-w), and characters(-m) of files
nl # number lines of files
head -n <number> # output the n first lines of files
tail -n <number> # output the n last lines of files
sort # sort lines of text files (use flag -r for reverse). Use -n to sort numerically
uniq # remove adjacent duplicated lines from input. Use -c to see number of times the line occurred
find <dir> -name file_name # search for files in a directory hierarchy by name. Use -iname for case insensitive search
which # locate a program file in the user's path
history # show history of commnads
!<number> # rerun the command with the number from history
!! # rerun the last command (bang bang)
bc # Bash calculator language ex. echo '3 + 4' | bc
clear (ctrl+l) # clear terminal
exit (ctrl+d) # to exit
For practice, let’s create two text files including some names and
grades by cat
command in bash_test
directory:
mkdir bash_test
cd bash_text
cat > names.txt
Dori
Ari
Ashi
Jackie
Dori
# press `ctrl+d` to exit
cat > grade.txt
A
B+
A-
A
B
# press `ctrl+d` to exit
ls
ls
command returns grade.txt names.txt
that shows we already made the files. Now, let’s see head, tail and
number of lines in both files:
head -n 3 n*.txt
echo ---
tail -n 3 g*.txt
echo ---
wc -l [n,g]*.txt
## Dori
## Ari
## Ashi
## ---
## A-
## A
## B
## ---
## 5 grade.txt
## 5 names.txt
## 10 total
For finding things we can use grep
or “global/regular
expression/print” command. For example, let’s find lines that contain
the letter “D”:
grep D names.txt
## Dori
## Dori
There are several options that we can use for grep
command. For example, grep -w
is searching for the exact
word, -n
option shows numbers the lines that match,
-i
flag makes our search case-insensitive, or
-v
inverts our search to the lines that do not contain
the pattern, or -o
print only the matched parts, and
-P
flag for using Perl-compatible regular
expression. To see all the option use man grep
. Lets’
try to find lines which do not contain letter “d” or “D”:
grep -inv d names.txt
## 2:Ari
## 3:Ashi
## 4:Jackie
While grep
finds lines in files, the find
command finds files themselves. For instance, in directory
bash_test
command find .
will shows all
files and directories within the current directory. The following
command will return number of lines in names.txt
and
grade.txt
files in the directory:
wc -l $(find . -name '[n,g]*.txt')
## 5 ./grade.txt
## 5 ./names.txt
## 10 total
For another example, you may use the command in below to print a
divider, like ===
, followed by date and hostname:
echo === $(hostname) $(date)
# Or
echo === $(hostname) "date: $(date)"
Pipes and Filters
Now that we know a few basic commands, we can combine the programs and commands in new ways. The following commands let us to use output of a command as an input for another command or store the outputs of commands in a separate file.
first | second # is a pipeline; the output of the first command is used as the input to the second
command > file # redirects a command’s output to a file (overwriting any existing content)
command >> file # appends a command’s output to a file
< # operator redirects input to a command
For example let’s remove the duplicated names in the
names.txt
:
sort names.txt | uniq
echo --- To count number of occurrences ---
sort names.txt | uniq -c
## Ari
## Ashi
## Dori
## Jackie
## --- To count number of occurrences ---
## 1 Ari
## 1 Ashi
## 2 Dori
## 1 Jackie
Or make a new file, count.txt
, including number of
lines, words, and characters in the text files:
wc [n,g]*.txt > count.txt
Use cat count.txt
to see the file content. Also, you
may use:
cat count.txt
wc -l < count.txt
## 5 5 12 grade.txt
## 5 5 26 names.txt
## 10 10 38 total
## 3
To find number of lines in the count.txt
. Note that
you also can use wc -l count.txt
to find the number of
lines.
Loops and conditional constructs
Loops are key to productivity improvements through automation as they allow us to execute commands repeatedly. Similar to wildcards and tab completion, using loops also reduces the amount of typing and mistakes. The syntax is:
for variable in file1 file2 ...; do command_1 $variable; command_2; ...; done
# Or
for output in $(command); do command_1 $output; command_2; ...; done
For instance, let’s make a copy of grade.txt
and
names.txt
:
for x in [g,n]*.txt; do cp $x copy-$x; echo copy-$x; done
## copy-grade.txt
## copy-names.txt
Use ls
to see new files that start with
copy-
in your directory. Another example,
for y in $(seq 1 3); do echo "The number is $y"; done
echo --- Same as ---
for y in {1..3}; do echo "The number is $y"; done
## The number is 1
## The number is 2
## The number is 3
## --- Same as ---
## The number is 1
## The number is 2
## The number is 3
Conditional statements help us to write an if
construction. In general we can write the test statement by
[ Expression ]
. The syntax is:
if [ Expression ]; then command; elif [ Expression ]; then command; ...; else command; fi
For example, let’s print “File exist” if count.txt
is
exist (note that there is a space after [
and before
]
):
if [ -e count.txt ]; then echo "File exist"; else echo "File does not exist"; fi
echo --- Or ---
if [ ! -e count.txt ]; then echo "File does not exist"; else echo "File exist"; fi
echo --- Or ---
if [ ! -e count.txt ]; then echo "File does not exist"; elif [ -e count.txt ]; then echo "File exist"; else echo "NA"; fi
## File exist
## --- Or ---
## File exist
## --- Or ---
## File exist
To see all the test expressions see man test
.
Text editors
Most popular text editors in Bash:
- Vi
- Nano
- Emacs
To open the text editors simply run vi
,
nano
or emacs -nw
. You may use
ctrl+z
to suspend the editor and return to the Bash
terminal and enter fg
in the Bash terminal to return the
editor. To exit, in Vi first press esc
and then enter
:q!
, in Nano you may use ctrl+x
, and in
Emacs ctrl+x ctrl+c
. Vi and Emacs have more futures in
comparison to Nano but they are more difficult as well.
The following are some important commands in Nano. Note that
^
is ctrl
and M-
is
alt
.
^s
: save^o
: write out (save with a new name)^x
: exit^z
: suspend nano (if activated)^k
: cut the lineM-6
: copy the line^u
: uncut/paste the line^w
: where is (search)^\
: search and replaceM-g
: go to lineM-a
: select textM-u
: undoM-e
: redo^t
: spelling check (need to installspell
package)^j
: justify text^g
: help (F2
)
The following are some important commands in Emacs. Note that
C-
is ctrl
and M-
is
alt
.
C-x C-c
: exitC-z
: suspendC-k
: kill the lineC-w
: cut the line/textM-w
: copy the line/textC-y
: uncut/paste the line/text (yank)C-space arrow keys
: select textC-shift arrow keys
: select paragraphsC-x u
: undoC-a
: move to the beginning of the lineC-e
: move to the end of the lineC-home
: move to the beginning of the bufferC-end
: move to the end of the bufferM-g g
: go to lineC-s
/C-r
: searchM-%
: replace (y
yes,n
no,!
all)C-g
: stop a commandC-x C-f
: make/open a file as a new bufferC-x b
: change the bufferC-x k
: kill the bufferC-x 1
: close other windowsC-x 0
/q
: close/quit windowsC-x o
: switch to other windowsC-h ?
: help listC-h t
: tutorialC-h d
: search help for a patternC-h c
: show help for the commandM-x <command>
: run commandsM-x ispell
: spell check; enter the suggesteddigit
ora
to accept orr
to rewriteM-x package-install
: install packagesM-x package-list-packages
: list of packages
You may find more about Emacs in here.
Shell script
Now, we can make Shell script to crate a small program including
Bash commands and other programs that we want. Let’s make a program to
shows rows 3 to 5 of a file in Shell scripts. Use
nano script.sh
to open nano
text editor to
make script.sh
and insert the following lines:
#!/bin/bash
sort names.txt | head -n 5 | tail -n 3
The first line shows the language of the program which is Bash in
here. To run the program use: {bash} bash script.sh
You may use the following program to show rows 3 to 5 of a given
file. Use nano script_1.sh
and insert the following
lines:
#!/bin/bash
sort "$1" | head -n 5 | tail -n 3
To run the code use:
bash script_1.sh names.txt
## Dori
## Dori
## Jackie
Also we can write a program that works for any given files. Use
nano script_all.sh
and insert the following lines:
#!/bin/bash
for line in "$@"; do sort $line | head -n 5 | tail -n 3; done
To run the code use:
bash script_all.sh names.txt grade.txt
## Dori
## Dori
## Jackie
## A-
## B
## B+
For another example let write a program to find a certain pattern
within some files in bash_test
directory. Use
nano name_select.sh
and insert:
#!/bin/bash
grep -w $1 -r $2 | cut -d : -f 2 > $1.txt
To find name Dori
among all files in the current
directory (.
) use:
bash name_select.sh Dori .
To see the output run cat Dori.txt
.