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 causerm
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 likeVAR2="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.
Readings
Read chapters 3, 4, 7, and 8 in the Software Carpentry tutorial.
Here are a couple of tutorials you can reference:
- Bash programming intro 1; pretty short and more introductory.
- Bash programming intro 2; much more detailed.
Homework
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.Suppose you have a folder called
BACKUP
in your home directory. Create a function calledbackup
that copies a single specified file to theBACKUP
folder. For example:backup file1
should copyfile
toBACKUP
.Working with the same
BACKUP
directory, create a script or function that copies a single specified file toBACKUP
, but with a name that reflects the current date.For example,
backup-date file1
should copyfile
toBACKUP
with a new name likefile1-2012-04-08
.The
date
command can be used to get the current date with a desired format. For example, the output ofdate +%Y-%m-%d
would give the date in the format shown above.Create a script called
recycle
that acts as a somewhat safer replacement for therm
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.