*nix

The phrase *nix refers to family of operating systems descended from Unix, e.g. GNU/Linux, Mac OSX, BSD... that share a common philosophy for how a computer should work. Ideally these operating systems obey the POSIX standard, and most do at least partially.

Shell

A (for our purposes, text-based) user interface to an operating system. A shell allows you to run programs and see their output. Common shells include:

  • bash
  • tsh
  • zsh
  • csh
  • fish

Terminal

A program (graphical or otherwise) that allows you to interact with a shell program.

Getting started

To get started, you should open a terminal (which will launch your default shell, probably bash). Do this like you would any other program on your operating system of choice.

Running a program

To run a program in the shell, we simply enter the name of that program. For example, to run Python 3 we would write:

$ python3
Python 3.4.3+ (default, Oct 14 2015, 16:03:50)
[GCC 5.2.1 20151010] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

When we enter the name of a program to be run, the shell checks a list of directories for an executable matching that name. We can ask which program is being run with the which command.:

$ which python3
/usr/bin/python3

This tells us the absolute path to the program we are running. This means we could instead run:

$ /usr/bin/python3
Python 3.4.3+ (default, Oct 14 2015, 16:03:50)
[GCC 5.2.1 20151010] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

The list of directories we search is found in the $PATH environment variable. We can list the contents of an environment variable with the echo program.:

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:~/bin

We can see that $PATH contains a colon-delimited list of directories to search for a program to run. Note that the current directory, ., is not listed. If we created a program called myprogram in our home directory that we wanted to run and we ran just myprogram, we would get the following

$ myprogram myprogram: command not found

We would instead need to run:

$ ~/myprogram
Hello!

Since we specified a path to the program, we bypass searching $PATH.

Managing files

One of the most common tasks in the shell is to look around to find files, copy them, rename them, or delete them. We can see what is in our current directory with the ls program:

$ ls
Documents  Downloads  Music  Pictures

(This is a greatly abbreviated listing.) We can of course look in different directories:

$ ls Downloads
3300.tex  gurobi5.6.3_linux64.tar.gz

The cp program copies files, while the mv command moves or renames files. They both use the same syntax.:

$ cp original-file copy-file
$ mv original-file new-file

The rm command deletes files.:

$ rm new-file

Please use caution when running rm, especially with flags such as -r or -f, which causes rm to recursively delete sub-directories and fail to ask for confirmation when doing so, respectively.

Input/output redirection

Each program has three ways to perform I/O: standard input, standard output, and standard error (abbreviated stdin, stdout, and stderr, respectively). Programs can read input from stdin and write output to either stdout or stderr. stdout is used for most output, while stderr is used to log errors. In a terminal, the text that shows up on your screen is from both stdout and stderr.

We can redirect stdout and stderr to files. To redirect stdout, we use >. To redirect stderr, we use 2>.:

$ ls > list_of_files
$ ls 2> any_error_messages
Documents  Downloads  Music  Pictures
We can of course do both at the same time.::
$ ls > list_of_files 2> any_error_messages

and even redirect both to the same file. Order matters, here.:

$ ls > list_of_files_and_errors 2>&1

We can also connect the stdout of one program to the stdin of the next.:

$ pwd | ls

is a contrived way to list the contents of the current directory. More useful would be something like:

$ ls -1 | grep '.*py$' | grep -v '^test_' | wc -l

This lists all files in the current directory, one per line, then finds all lines that end in .py, then removes all lines that begin with test_, and then counts the number of lines remaining. This would be one way to count the number of Python files in the current directory that don’t begin with test_.

Another (more dangerous) command recursively removes all backup files made by Emacs under the current directory, which are marked by a trailing ~.:

$ find . -name '*~' -print0 | xargs -0 rm

Getting help

The man program displays the manual page for most programs (and C and C++ header files).:

$ man git

shows a (perhaps not very useful) introduction to the git program. If you were trying to figure out how to use ls to print more information about files,:

$ man ls

would teach you about the -1, -a, -l, and -h flags.:

$ man bash

will teach you that writing any non-trivial program in Bash is a nightmare.:

$ man man

might technically be enough for you to learn everything on this page without reading it.