The Shell

The graphical user interface of desktops like Gnome, KDE, or Cinnamon are ideal for the majority of end users. However, once a certain level of proficiency is achieved, users often look for addded functionality, especially where automation of frequent tasks is concerned. The Unix shell is ideal for those willing to invest some learning time to achieve a much more powerful environment. Open a Terminal (usually somewhere like Applications/Accessories) to start a shell. A blinking cursor waits for your input. Enter a command, and terminate with the Newline key. Here are some commands to try:

ls list of files, names only
ls -s list of files with number of allocated 1K blocks
ls -la long list of all files with byte count of file contents
mkdir tmp make new directory tmp
cd tmp change working directory to tmp
pwd print working directory
cd change to home directory
cp x y copy file x to y
mv x y move (rename) file x to y
if y is dir: move x into y
rm x remove file x
rm -rf x remove x and subdirs (careful!)

Use the text editor nano (previous versions were called pico) to create a new text file.

nano newfile.txt

Type a couple of lines and finish with Ctrl-O, then Return, then Ctrl-X. Enter

ls

at the shell prompt and see the new file name in the list.

The shell contains a lot of features to save you work:

File types and permissions

Unix programs always run with a certain userid and limited permissions, similar to the interactive work of human users in the shell. Therefore, permissions apply not just to human users, but more importantly to programs, as well.

This permission concept, together with the robust implementation of multi-user and multi-tasking, makes Unix and therefore Linux a very safe operating system that is rarely plagued by malware from mail attachments and similar sources; viruses, so well-known and feared in other operating systems, are virtually unknown in Linux.

Other types of attacks through the network are of course still possible. Therefore, every system continously exposed to the Internet should receive regular security updates. Linux distributions typically facilitate or even completely automate that task.

Print a long listing of all files (including hidden ones) with

ls -la

This also shows the permissions; for the text file just created with the editor they should be:

-rw-r--r--

The first character indicates the type, such as

The next three characters indicate the read (r), write (w), and execute (x) permission for the owner, the group, and others. The write permission includes deleting. For directories x means change into.

In listings the single dot (.) stands for the current directory, the double dot (..) for the parent directory. Your home directory should have the permissions

drwxr-xr-x

meaning that you can read and write; your group and everyone else can read but not write.

The command chmod is used to change the permissions:

chmod go-r newfile.txt

Now nobody except yourself can read the file.

chmod go+r *.txt

The wildcard * means everything, and in this case includes the newfile.txt.

Environment variables

The variables are used by the shell for various tasks, such as to communicate options to applications:

env

E.g., if you have a private Java version installed that is different from the system-wide one, use the JAVA_HOME environment variable to specify the directory with you own installation:

export JAVA_HOME=$HOME/jdk1.6.0

echo $JAVA_HOME

Such environment variables are usually set in the file .bashrc in your home directory. Be careful when you edit this file, as it is executed whenever you start a shell.

Pipe

Commands up to this point have delivered their output to the terminal. In many cases we want further processing on that output. Consider the following:

ls *.txt | wc -l

The result of ls is a list of filename; this list is forwarded to the command wc (word count) which counts lines, words, and bytes (the option -l only counts lines). The wc command uses its standard input as the data source, which is connected to the standard output of the ls command via the pipe. This construct is very useful for creating more complex commands from simple ones.

stdin, stdout, and stderr

The following command sends the content of file1.txt as standard input to wc, and collects the standard output in cnt.txt:

wc < file1.txt > cnt.txt

This useful for programs that are called by automated scripts, or that run very long:

bigStatistics < largeInput.dat > largeOutput.dat 2>error.log

The Standard error in this case is collected in an error.log file. If it is of no interest we can write:

prog < input > output 2>/dev/null

The null device acts as a sink with no storage.

nohup

Programs that are expected to run for a very long time can be sent into the background:

bigjob -some -options < input.txt > output.txt &

The process will continue to run while the shell is active. If you want it to continue to run after you logged out, use nohup:

nohup bigjob &

This is reminiscent of the time when communication with mainframe system was done via phone lines (no hangup).

Shell Scripts

The automation of frequent tasks can be done with shell scripts. Here is a simple example:

#!/bin/sh
 
date
pwd

Use your text editor to create a file named doit, and use

chmod +x doit

to set the execute permission for the script named doit. Use

./doit

to run the script.

Unix searches for commands in a list of directories specified in the environment variable PATH:

echo $PATH

You can add the current directory to that list, but it is considered safer to dedicate a directory for user-defined scripts, such as $HOME/bin. Put the following line at the end of your .bashrc (careful!):

export PATH=$PATH:$HOME/bin

Create your bin directory:

cd
mkdir bin

Move the doit script into the bin directory:

mv doit bin/

The trailing slash is not necessary, but it specifies that bin is meant as a directory name. Otherwise, if bin does not exits, the effect would be to rename doit to bin.

Open a new shell (by opening a new terminal) and try the new command doit!