08 Apr 2012 [ 185 week13 ]

Shell initialization and aliases

When you start an interactive Bash shell, it reads several files to customize your environment. The one we'll customize is ~/.bash_profile (~ indicates your home directory). This file contains commands that are run when you start a new Cygwin window (the ~/.bashrc file is run when you start a new shell after that, like if you type the bash command). You should edit the file using the nano command, so that it will save it with the Unix line endings that Cygwin expects.

If you find that you frequently use the same special command, you can assign it a shorter name (an alias) using the alias command. This just tells the shell to replace the short command name with the full version every time it appears. Some examples:

You'll usually define aliases in your .bashrc.


Variables work much like on the Windows command line, with a few small differences. Here's a sample shell session:

$ GREETING="Hello there."
$ echo $GREETING
Hello there.
$ printenv GREETING
$ export GREETING
$ printenv GREETING
Hello there.
$ LONG_GREETING="Hello hello... $GREETING"
Hello hello... Hello there.
$ SINGLE_QUOTES='Hello hello... $GREETING'
Hello hello... $GREETING

A few things to notice:

Cygwin/Unix/Linux/etc. use a PATH variable just like Windows. The only difference is that it's usually a colon-separated of directories, rather than semicolon-separated:

$ echo $PATH

Command substitution

You can treat the output of a command much like a variable, with similar syntax:

$ pwd
$ DIR="My working directory is: $(pwd)"
$ echo $DIR
My working directory is: /home/jlepak

In the above example, $(pwd) was replaced with the output from the pwd command.

Functions and scripts

You can create scripts by inserting a bunch of commands (just like ones you would type) into a file. There is special syntax for defining functions, which work mostly work just like scripts.

Basic setup

Here's a very basic script:

#!/usr/bin/env bash

echo 'Hello there!'

The top line is used by the shell to determine what program actually runs the script. We'll only be talking about Bash scripts, so you'll always have that same line at the top. # usually indicates a comment, but if the first line of a script starts with #! it is used to identify the program that runs the script.

Copy that text into a file called hello.sh, and then try to run it (note that you have to include the directory name, using . to indicate the current directory, unless . is in your PATH):

$ ./hello.sh
-bash: permission denied: ./hello.sh

The reason for such an error (if you get an error) is that you need to set the file permissions properly in order to run it as a program:

$ chmod u+x hello.sh
$ ./hello.sh
Hello there!

chmod changes the file mode (file permissions), and u+x indicates that the user (owner of the file) should be able to execute it.

Alternately, you can just explicitly tell Bash to run your program:

$ bash hello.sh
Hello there!

In that case, you don't need the top line of the script either.

Providing input for scripts and functions

The main way of providing input to scripts or functions is through the command line arguments. These are available in special variables: $1, $2, etc. hold the command line arguments.

The special variable $@ refers to all of the command line arguments, which you can pass on to other commands.

To create interactive scripts, you can use the read command, which reads a line of input and stores it in a named variable:

$ read NAME
Joel (typed by user)
$ echo $NAME


If you have a commonly used operation that's a little too complex to use a simple alias, you can define a function in your .bashrc. Other than the notation, functions work just like scripts:

$ hello () {
    echo "Hello ${1}."
$ hello Joel
Hello Joel.


Read chapters 3, 4, 7, and 8 in the Software Carpentry tutorial.

Here are a couple of tutorials you can reference:


  1. How would you create an alias for a command that changes your current directory to the Windows Program Files directory? Experiment with using the alias command to do this. You might have to be careful with how you use quotes.

  2. Suppose you have a folder called BACKUP in your home directory. Create a function called backup that copies a single specified file to the BACKUP folder. For example: backup file1 should copy file to BACKUP.

  3. Working with the same BACKUP directory, create a script or function that copies a single specified file to BACKUP, but with a name that reflects the current date.

    For example, backup-date file1 should copy file to BACKUP with a new name like file1-2012-04-08.

    The date command can be used to get the current date with a desired format. For example, the output of date +%Y-%m-%d would give the date in the format shown above.

  4. Create a script called recycle that acts as a somewhat safer replacement for the rm command, moving the input files to ~/RECYCLE-BIN instead of deleting them. Optional: have your command keep a log of the original locations of each file, in order to let you undelete them back to their original locations later.