Learning the Command Line – Shell Scripts

Terminal commands are great but what if you want to have something done every time you login? What if you need to do something on several files or some other repetitive action and don’t want to type in the commands every time. That could get time consuming and dreary. In this article, we will set up our Terminal environment to make certain things a little easier and get a start on shell scripting.

A shell script is a text file with all the commands you want run, one after another. It’s almost like a regular programming language but in many ways easier to use.

Open Terminal and type:

cp /etc/bashrc .bashrc
cp /etc/profile .bash_profile

This will copy bashrc and profile to your home directory. Notice we renamed profile to bash_profile and made both hidden with the preceding dots. They’re hidden because they shouldn’t be messed with on a regular basis, only when necessary. These are setup files for bash, the shell. They can allow us to do magic as we’ll see in the next article on changing the command prompt.

A plain-jane .bash_profile looks like this:

# System-wide .profile for sh(1)

if [ -x /usr/libexec/path_helper ]; then
        eval `/usr/libexec/path_helper -s`

if [ "${BASH-no}" != "no" ]; then
        [ -r /etc/bashrc ] && . /etc/bashrc

Some people just name it .profile. When a non-login shell, which is what you have when you start Terminal, starts it looks for files in this order:

~/.bash_profile, ~/.bash_login, and ~/.profile

So if you name it .profile and you have a .bash_profile, it’ll never get read.
I’m not sure when Apple changed it but it no longer sources, or reads into memory, the .bashrc file. So you need to add this:

# include .bashrc if it exists

if [ -f ~/.bashrc ]; then
    source ~/.bashrc

# set PATH so it includes user's private bin if it exists

if [ -d ~/bin ] ; then

The first if statement sources or reads the .bashrc file. The second looks to see if you have a bin folder in your user folder. This one is not really necessary unless you’re a programmer and/or you like to keep programs in your user space instead of /usr/local/bin. We need the .bashrc file because this is where we’re going to put our aliases and other things we need when Terminal starts up.

Here is the .bashrc file you copied:

# System-wide .bashrc file for interactive bash(1) shells.
if [ -z "$PS1" ]; then

PS1='\h:\W \u\$ '
# Make bash check its window size after a process completes
shopt -s checkwinsize
# Tell the terminal about the working directory at each prompt.
if [ "$TERM_PROGRAM" == "Apple_Terminal" ] && [ -z "$INSIDE_EMACS" ]; then
    update_terminal_cwd() {
        # Identify the directory using a "file:" scheme URL,
        # including the host name to disambiguate local vs.
        # remote connections. Percent-escape spaces.
	local SEARCH=' '
	local REPLACE='%20'
	printf '\e]7;%s\a' "$PWD_URL"
    PROMPT_COMMAND="update_terminal_cwd; $PROMPT_COMMAND"

About aliases: These are not aliases like you’re used to in Finder. In this context, aliases are shortcuts for Terminal commands. For example; you could set up an alias where you type a word and several things happen. I have one where I type ‘work’ and the shell changes directory from where I am to my working directory in my user folder. This comes in handy.
The format for creating an alias is:

$ alias nameofalias='command'

In this case it would be: $ alias work=’cd ~/working’. There are no spaces between the name of the alias, the equals sign, or the command. And yes you need the tic marks on the actual command (‘ ‘).
Here are some examples of aliases you might use:

# set up aliases

alias ll='ls -laghF'
# gives a long listing of the current directory - if you want to know what the switches are do a 'man ls'
# note: ls is built into the shell and is not a separate command

alias l='ls -laghF'
# same as above but only one letter - I'm lazy

alias netconns='netstat -a -f inet'
# gives a listing of Active net connections

alias cd..='cd ..'
# a fix in case you forget the space between cd and ..

alias ..='cd ..'
# a shortcut to go up one level or the enclosing directory 

alias cls='clear'
# clears the screen

# Some more alias to avoid making mistakes:
# remove the # if you want to use these

#alias rm='rm -i'
#alias cp='cp -i'
#alias mv='mv -i'
# these are the commands with the interactive switch set - it will ask you 'are you sure?' for each instance
# helps newcomers avoid deleting something they shouldn't

alias ttop='top -ocpu -R -F -s 2 -n30'
# a slightly more usable top command - again use the man command on top if you want more information

If you’re unsure of what you might need or can use, there are all kinds of suggestions on various web sites. Most are for Linux but most of those can be used on OS X. If you want you can copy/paste these into your .bashrc file. You must use nano or vim or even emacs unless you have an application that can edit hidden files like BBEdit.

You’ll notice some of the above starts with a #. This tells the shell that the following on the line is a comment and not something to be run as a command. In the case of some of the aliases that begin with #, they are ‘commented out’ and wont run. If you want them to be run, remove the #.

You can also change your $PATH variable in the .bashrc script. For example, in the above where you added to .bash_profile, you added your ~/bin directory to the $PATH. This allows you to type in a command without having to type in the whole bath in the command. For example:

$ neatgameIwrote
instead of
$ ~/bin/neatgameIwrote

The $PATH variable stores locations or paths to directories where commands are kept. An unmodified $PATH might look like this: /usr/sbin:/sbin:/usr/local/bin

The addition in the .bash_profile added your ~/bin so it would look like this: ~/bin:/usr/sbin:/sbin:/usr/local/bin
.bashrc is also where you put functions, which are different from aliases in that functions are small pieces of code which are called whenever you type it’s name. If you have a small repetitive job to do, you might want to consider making it a function. Functions will be discussed in another article as in this one I just wanted to get your shell set up and ready for other things.

My next article is not so much a tutorial as showing how you can use aliases in everyday use and have a little fun changing the command prompt.