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`
fi

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

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
fi

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

if [ -d ~/bin ] ; then
    PATH="~/bin:${PATH}"
fi

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
   return
fi

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'
	local PWD_URL="file://$HOSTNAME${PWD//$SEARCH/$REPLACE}"
	printf '\e]7;%s\a' "$PWD_URL"
    }
    PROMPT_COMMAND="update_terminal_cwd; $PROMPT_COMMAND"
fi

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.

 

9 Comments: 

  1. TattooedMac's Avatar
    Thanks Van for taking the time for the command line.
    Its a shame there are so many scared of it, but I'm happy I'm doing my part in learning it, so I can help myself.
    Im currently going through Take Control of the Mac Command Line with Terminal which is very well written, and takes it easy on those that don't know. Joe teaches well trough a eBook. Now for your 2nd article
  2. cradom's Avatar
    Err...Brent? That's one of my pieces. Glad you like it.
  3. TattooedMac's Avatar
    Doh, my bad Craig. Presumption doesn't get you far these days, as I didn't really read the Author but just assumed from Van making the thread.
    But yes I do like it thank you
  4. vansmith's Avatar
    I'm happy to take the credit though...
  5. cradom's Avatar
    Uh huh...
    Anyone looked at the new one yet?
  6. TattooedMac's Avatar
    No its not where the one I read is ??
  7. cradom's Avatar
    Hasn't been published yet, hence the question.
  8. TattooedMac's Avatar
    Ahhh aimed @ Van . . .. So Vansmith ?? Has it been edited yet and ready for Publication ?
  9. cradom's Avatar
    Not necessarily aimed at him, he's not the only one who can do this. And he's been busy.
Leave a Comment