08 Apr 2012

### 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:

• alias ls='ls --color=tty' will give colorized output in a terminal.
• alias rm='rm -i' will cause rm to always prompt before deleting.

You'll usually define aliases in your .bashrc.

### Variables

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"
$echo${LONG_GREETING}
Hello hello... Hello there.
$SINGLE_QUOTES='Hello hello...$GREETING'
$echo$SINGLE_QUOTES
Hello hello... $GREETING  A few things to notice: • You have to quote values on the right hand side of an assignment if they contain spaces. In general, quoting rules are very complicated, but the common cases are pretty easy. • You can't leave space around the = (like the Windows shell). • You use a variable by prefixing it with $, rather than surrounding with % like in the Windows shell.
• Programs you start from the command line (like printenv, which is used to print the values of environment variables) can't see the values you set unless you export the variables.
• Variables can expand inside double quotes, but not single quotes. Single quotes are used when you want to avoid expanding variables or other special characters.
• $VAR and ${VAR} usually work the same, but the second form has more options, and can be used when you want to do something like VAR2="xx${VAR}xx". 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 /usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/share/java/ apache-ant/bin:/opt/java/bin:/opt/java/db/bin:/opt/java/jre/bin:/usr/bin/core _perl:/home/jlepak/bin:/opt/java/bin:/home/jlepak/bin:/opt/java/bin  ### Command substitution You can treat the output of a command much like a variable, with similar syntax: $ pwd
/home/jlepak
$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 Joel  #### Functions 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:

### Homework

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.