If you’ve been learning the command-line and you have the basics down (you should be, as the most effective way to use a computer is a combination of a GUI and command-line), the next step is to customize your environment.
Beginner’s Tip: “command-line” and “shell” are often used synonymously. In unix, technically speaking, the shell is what processes the command-line, but usually, they mean the same thing
The ability to fully customize your shell is one of the most powerful things about the command-line. It’s a dry subject, and mastering it won’t get you favors from the opposite sex (although it should), but it can be very useful.
There are many ways to customize your shell, but the first one you should learn is modifying your Bash startup files (assuming your shell is Bash, which is the default in OS X, Linux, and many other unices).
When I first learned how to customize bash, I found an overwhelming amount of information and opinion, which made it difficult. This article is intended to give you the fundamental concepts so that you can create your own startup files, and understand how they work. To give you an example, I go through a subset of my own files, section by section.
Let’s install the example startup files
Beginner’s Tip: Directory and folder are synonymous. Often folder is used in Windows and OS X and directory is used in Linux, however even Linux represents a directory as a folder graphically
Below are the two example startup files: .bashrc and .bash_profile.
If you would like to use these as your startup files, follow the following directions for your OS.
OS X:
If you want a backup of your existing files, use the following commands (if the files don’t already exist, you will get an error. The files will be named .bashrc_ORIGINAL and .bash_profile_ORIGINAL in your home folder):
cp ~/.bashrc ~/.bashrc_ORIGINAL ; cp ~/.bash_profile ~/.bash_profile_ORIGINAL
Copy .bash_profile and .bashrc to your home folder.
There are a variety of ways to do this, but the simplest is to use the curl command:
curl -o ~/.bash#1 “http://assets.toddwerth.com/settings/dotfiles/osx/.bash{rc,_profile}”
You do not need to log out, just create a new window or tab in iTerm, or a new window in Terminal.
Linux and other unices:
If you want a backup of your existing files, use the following commands (if the files don’t already exist, you will get an error. The files will be named .bashrc_ORIGINAL and .bash_profile_ORIGINAL in your home folder):
cp ~/.bashrc ~/.bashrc_ORIGINAL ; cp ~/.bash_profile ~/.bash_profile_ORIGINAL
Copy .bash_profile and .bashrc to your home directory.
There are a variety of ways to do this, but the simplest is to use the wget (or curl for BSD and others) commands:
wget -O ~/.bashrc “http://assets.toddwerth.com/settings/dotfiles/generic/.bashrc”
wget -O ~/.bash_profile “http://assets.toddwerth.com/settings/dotfiles/generic/.bash_profile”
or
curl -o ~/.bash#1 “http://assets.toddwerth.com/settings/dotfiles/generic/.bash{rc,_profile}”
Log out then log back in in order to load .bash_profile. Alternatively, you can do a source ~/.bash_profile to run the files.
What the heck are bash Startup Files?
Beginner’s Tip: ~ represents your home folder, it is short-hand notation so that you don’t have to type the whole thing; it is also used when you don’t know the home folder; for example, my code above works, no matter where your home folder/directory is.
Bash, as well as other unix shells, have files that run when they start. You can modify these files to set preferences, create aliases and functions (a kind of micro-script), and other such fun.
When you start an interactive shell (log into the console, open terminal/xterm/iTerm, or create a new tab in iTerm) the following files are read and run, in this order:
/etc/profile
/etc/bashrc
~/.bash_profile
~/.bashrc (Note: only if you call it in .bash_profile or somewhere else)
When an interactive shell, that is not a login shell, is started (when you call “bash” from inside a login shell, or open a new tab in Linux) the following files are read and executed, in this order:
/etc/bashrc
~/.bashrc
Beginner’s Tip: Normally you can’t see the . files (files that start with a period) because they are hidden. Depending on your OS, you can simply turn on hidden files. Another option is to open the file in the command-line. Here are a few examples:
In shell: pico .bashrc
In shell: vi .bashrc
In OS X: open .bashrc
In GNOME: gedit .bashrc
/etc/profile and /etc/bashrc are run for all users on the system. Often on your workstation, there is only one user, you. But in systems with more than one user, these files can be used to set generic settings for all users. The files in your home folder, ~/.bashrc and ~/.bash_profile, are only for your particular user (since /etc/bashrc is run before ~/.bashrc, you can override anything in /etc/bashrc by simply setting it again in ~/.bashrc). Normally I only change these, since they are in your home folder, and only you have rights to them, you can change them without worry of affecting anyone else.
When your session starts, these files are run, just as if you typed the commands in yourself. Anything that normally works in the shell works in these files. Since .bash_profile only runs when you first login, you set very little there; the only important thing is your PATH. bashrc is where the meat goes, and will be where you spend all your time.
Comments, export, and aliases, the tools of the trade
The most common commands you use in your .bashrc and .bash_profile files are the following:
comments: A # starts a comment, which continues until the end of a line. The comments are not run by the system, and are only there for your information. Use them to make notes to yourself for future reference.
For example:
# A very interesting comment, sure to be read by everyone
alias foo=’bar’ # Another comment, dangling at the end of a line
alias: An alias is simply substituting one piece of text for another. When you run an alias, it simply replaces what you typed with what the alias is equal to.
For example, if you create an alias called foo and set it to “cd /etc”:
alias foo=’cd /etc’
Beginner’s Tip: To test your startup files, use the source command (. also works). It loads and executes a file in your current process (rather than starting a new process, which is normally what happens):
source .bashrc
In the command-line every time you type foo it is replaced by cd /etc. If you type foo ; ls it will be run as cd /etc ; ls.
To see what aliases are set on your system use the alias command. If run without any parameters it will list all the aliases.
Note: You can create a temporary alias by setting it in the command-line rather than in a bash startup file. Lets say you’re typing the same command over and over as you’re working on some task. Just set an alias (alias foo=ThingImDoingOverAndOver). It will only exist in your current session.
export: Export sets an environment variable. Various environment variables are used by the system, or other applications, such as grep, or bash itself. They simply are a way of setting parameters that any application/script can read. If you set a variable without the export command, that variable only exists for that particular process (for example if you set a variable in a script, only that script can access it). You do this like so:
FOO=1234
If you want that variable to be accessible by other child processes (which is a fancy way of saying by everything) then you simply use the export command to make it permanent (technically it isn’t permanent, but if you set it in your bash startup scripts it will be available to everything you run in bash, which basically means everything.). To make FOO, which we just set, permanent, we do the following in our .bashrc file:
export FOO=1234
It is common to make environment variables all upper case, as shown in the example.
Bash has a set of environment variables you can set, such as the prompts (see below). Other applications use them too, such as GREP_OPTIONS for grep (see below). You can also create your own, to be used by you in the command-line or in scripts. In the color section below I create common colors to be used in the startup files, as well in other scripts I write.
To see what environment variables are set on your system use the set command. If run without any parameters it will list them.
To use an environment variable, you preface it with a $. A simple way to test this (assuming you set FOO already) is to print out the value using the echo command, like so:
echo $FOO
Creating your .bash_profile
The .bash_profile file runs when you first login. You can put everything in this file, but since it only runs once and doesn’t run when you start a non-login session, it is best that you put only the bare minimum, and then run the .bashrc file. With this approach, your .bashrc gets run every-time to start a new session, because it is called from .bash_profile on login, and it also gets run by bash automatically when starting a non-login shell.
The first thing to setup is your PATH. A path will already be set by the system, so you don’t want to overwrite that. You can add to the path like this:
# Add to original path
export PATH=/foo:/foo/bar:$PATH
The $PATH at the end represents the existing path; in otherwords, you are taking the existing path, whatever that is set to, and adding the paths /foo and /foo/bar to it.
It is a good idea to add your bin directory to your path, if you have it. It’s a standard place to add all of your scripts. The following lines will add the bin folder in your home folder to the path. The if statement simply checks to make sure it exists first before it adds it. This is safe to use even if there is no bin folder:
if [ -d ~/bin ]; then
export PATH=:~/bin:$PATH
fi
Next, we will run the .bashrc file. The source command reads and runs another file in the same session you’re in (the . command does the same thing and is synonymous with source).
source ~/.bashrc
If you like, you can show a welcome message. This only runs when you first log in. The following is an example welcome message (note the colors, which are set in .bashrc below):
echo -e “Kernel Information: ” `uname -smr`
echo -e “${COLOR_BROWN}`bash –version`”
echo -ne “${COLOR_GRAY}Uptime: “; uptime
echo -ne “${COLOR_GRAY}Server time is: “; date
On my workstation, it displays the following:
Last login: Wed Aug 29 09:55:37 on ttyp1
Welcome to Darwin!
Kernel Information: Darwin 8.10.1 i386
GNU bash, version 2.05b.0(1)-release (powerpc-apple-darwin8.0)
Copyright (C) 2002 Free Software Foundation, Inc.
Uptime: 10:41 up 47 mins, 3 users, load averages: 0.01 0.02 0.00
Server time is: Sat Sep 29 18:41:12 PDT 2007
Now the fun* begins, creating your .bashrc
* The word “fun” is used for entertainment purposes only. “Fun” or any other type of amusement is neither guaranteed nor expressly implied.
The .bashrc file is where the meat of your customization goes.
Normally it doesn’t matter in which order various items go, so the way the file is laid out is an individual preference. There are many ways to setup a .bashrc file, and many things you can use it for, there is no “right” way; only opinions on which is the right way.
In this section I’m going to go over some of the more common things you would use it for, as well as some things that are less common, but that I personally like. You can include as little or as much as you like in your own file.
ColorsTM
Colors aren’t the most important thing, truly, however because I use colors throughout the entire file, I need them to be created first.
I’ll start by turning on colors for misc things, the following set your terminal to be the color variant of xterm, turn on colors in grep, etc:
export TERM=xterm-color
export GREP_OPTIONS=’–color=auto’ GREP_COLOR=’1;32′
export CLICOLOR=1
OS X and BSD – The following command turns on colors in ls:
alias ls=’ls -G’
Linux, etc – uses the following to turn on colors in ls. You can specify exactly what color is used for what, which is very nice. See http://www.linux-sxs.org/housekeeping/lscolors.html for more information on setting specific colors:
alias ls=’ls –color=auto’
export LS_COLORS=’di=1:fi=0:ln=31:pi=5:so=5:bd=5:cd=5:or=31:mi=0:ex=35:*.rb=90′
Some standard colors, to make adding colors later in this file, or in scripts, easier:
export COLOR_NC=’\\e[0m’ # No Color
export COLOR_WHITE=’\\e[1;37m’
export COLOR_BLACK=’\\e[0;30m’
export COLOR_BLUE=’\\e[0;34m’
export COLOR_LIGHT_BLUE=’\\e[1;34m’
export COLOR_GREEN=’\\e[0;32m’
export COLOR_LIGHT_GREEN=’\\e[1;32m’
export COLOR_CYAN=’\\e[0;36m’
export COLOR_LIGHT_CYAN=’\\e[1;36m’
export COLOR_RED=’\\e[0;31m’
export COLOR_LIGHT_RED=’\\e[1;31m’
export COLOR_PURPLE=’\\e[0;35m’
export COLOR_LIGHT_PURPLE=’\\e[1;35m’
export COLOR_BROWN=’\\e[0;33m’
export COLOR_YELLOW=’\\e[1;33m’
export COLOR_GRAY=’\\e[0;30m’
export COLOR_LIGHT_GRAY=’\\e[0;37m’
alias colorslist=”set | egrep ‘COLOR_\\w*'” # lists all the colors
Here is an example of using a color in a script (note, the -e is required):
echo -e “The color ${COLOR_GREEN}green${COLOR_NC} is nice.”
Prompts ~/bin >
Beginner’s Tip: If you use different systems, a good trick is to check or import your startup files (and any other . files you like [. or dot files are hidden files and often used for settings]) into a source code repository, such as subversion. Then no matter what system you are on, assuming your subversion server is accessible, you can simply “checkout” your files with one command. Alternatively, you can store them on your website.
You can also do this with your ~/bin folder so you have your scripts too. It takes only a second to get them, and saves you time configuring the environment.
In the shell, every line begins with the prompt, right before the area you can type into. You can put a variety of different things in your prompt, from simply characters such as > to your user name, the name of the machine, or a ridiculous number of other things.
Some people’s prompts are, frankly, silly; do you really need your prompt to say something like this (note, the answer is “no”)?
juser@myMachine 1/1/2007 12:31:02 PM – “Funny quote of the day” – /home/juser>
I make my prompt as simple as possible, normally all you see is
~ >, which is just the path of the current folder followed by a “>”.
Knowing what user I am logged in as and which machine I’m on is also useful, but I put that in the window of my terminal (see below). For this very simple prompt, I use the following:
export PS1=”\\[${COLOR_GREEN}\\]\\w > \\[${COLOR_NC}\\]”
Since you can setup a .bashrc for each user, I normally set my regular user’s prompt to be green, and then I change it to red for root. This gives me a visual reminder that I’m logged in as root, and to be careful.
The following runs before the prompt and sets the title of the terminal window. If you set the window title in the prompt, weird wrapping errors occur on some systems, so this method is superior:
export PROMPT_COMMAND=’echo -ne “\\033]0;${USER}@${HOSTNAME%%.*} ${PWD}”; echo -ne “\\007″‘
Note: PROMPT_COMMAND, used in this way, causes problems when you are using the command-line directly (a non-graphical terminal, such as the system console). Simply disable this in those circumstances. You can also write a little if to check for that if you like.
Here is an alternative prompt, with the user and machine name:
export PS1=”\\[${COLOR_GRAY}\\]\\u@\\h \\[${COLOR_GREEN}\\]\\w > \\[${COLOR_NC}\\]” # Primary prompt with user, host, and path
Now I just set prompts 2 through 4. There is a lot of information on setting prompts, but to cover that would be a whole other article. I wanted to give you just the basics, if you want more in depth information follow this link.
export PS2=’> ‘ # Secondary prompt
export PS3=’#? ‘ # Prompt 3
export PS4=’+’ # Prompt 4
Navigation
In the command-line, you have to move around a lot. The following aliases are designed to help you navigate your file system with ease.
Here is a very simple and useful way to move back up the directory tree, two dots moves you up one, and three dots moves you up two levels in your path:
alias ..=’cd ..’
alias …=’cd .. ; cd ..’
A lot of people create a home alias, but this isn’t necessary. cd by itself, without any parameters takes you back to your home.
Another tip is to use cd – which takes you to the previous folder.
The following is very cool; I got it from this site. I modified it slightly to make it work a little better:
if [ ! -f ~/.dirs ]; then # if doesn’t exist, create it
touch ~/.dirs
fi
alias show=’cat ~/.dirs’
save (){
command sed “/!$/d” ~/.dirs > ~/.dirs1; \\mv ~/.dirs1 ~/.dirs; echo “$@”=\\”`pwd`\\” >> ~/.dirs; source ~/.dirs ;
}
source ~/.dirs # Initialization for the above ‘save’ facility: source the .sdirs file
shopt -s cdable_vars # set the bash option so that no ‘$’ is required when using the above facility
It basically allows you to save bookmarks to folders. If you constantly go to a particular directory, you can just set it as a bookmark like so:
save foo
This will set the current folder you are in as the bookmark foo. To get back to the folder, just type this:
cd foo
You can list your “bookmarks” with the show command:
show
foo=”/Users/joebob/foo”
The bookmarks are stored in the ~/dirs file, so you can edit them there too if you like.
Editors
If an application, such as Subversion, needs you to edit text. It will often launch an external editor and load the text into it. You can modify which application is launched by setting the EDITOR variable. I’ve listed various options below depending on your system:
#export EDITOR=’mate -w’ # OS-X SPECIFIC – TextMate, w is to wait for TextMate window to close
#export EDITOR=’gedit’ #Linux/gnome
#export EDITOR=’vim’ #Command line
export EDITOR=’pico’ #Command line
Misc
Common ls commands. Many people use these. ll shows the long listing, and lla shows the long listing with hidden files:
alias ll=’ls -hl’
alias la=’ls -a’
alias lla=’ls -lah’
Some very useful settings I like to set:
export HISTCONTROL=ignoredups # Ignores dupes in the history
shopt -s checkwinsize # After each command, checks the windows size and changes lines and columns
# bash completion settings (actually, these are readline settings)
bind “set completion-ignore-case on” # note: bind is used instead of setting these in .inputrc. This ignores case in bash completion
bind “set bell-style none” # No bell, because it’s damn annoying
bind “set show-all-if-ambiguous On” # this allows you to automatically show completion without double tab-ing
# Turn on advanced bash completion if the file exists (get it here: http://www.caliban.org/bash/index.shtml#completion)
if [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
Others you may find useful:
alias g=’grep -i’ #case insensitive grep
alias f=’find . -iname’
alias ducks=’du -cks * | sort -rn|head -11′ # Lists the size of all the folders and files
alias top=’top -o cpu’
alias systail=’tail -f /var/log/system.log’
Shows the commands you use most, it’s a cool script I got this from this site. It’s useful to show you what you should create aliases for:
alias profileme=”history | awk ‘{print \\$2}’ | awk ‘BEGIN{FS=\\”|\\”}{print \\$1}’ | sort | uniq -c | sort -n | tail -n 20 | sort -nr”
Subversion and Diff
This section is only useful if you use Subversion and diff. However, it highlights various things you can do with aliases and functions.
The basic concept is to wrap a bunch of commands, giving them a new naming convention. In this case the command is svn, and it has many options, such as svn status. By wrapping these commands, you can set common parameters that you use all the time. Also since they are aliases, you can use bash completion (set above) to get a nice list of the commands. For the following, if I just type sv and tab, I get a list of commands.
Some of these aliases simply wrap the original commands, without modifying them. I do this for consistency, and it gives me the opportunity to change them later.
First we set some standard settings for Subversion:
export SV_USER=’juser’ # Change this to your username that you normally use on Subversion (only if it is different from your logged in name)
export SVN_EDITOR=’${EDITOR}’
The next alias is interesting, as I’m basically using it to provide help to myself. Of course if you know subversion well, you don’t need this, but it may be useful when you’re first starting out and learning. When you type svshowcommands, it prints out a nice colored description of all the commands. Notice how you can have one alias on multiple lines:
alias svshowcommands=”echo -e ‘${COLOR_BROWN}Available commands:
${COLOR_GREEN}sv
${COLOR_GREEN}sv${COLOR_NC}help
${COLOR_GREEN}sv${COLOR_NC}import ${COLOR_GRAY}Example: import ~/projects/my_local_folder http://svn.foo.com/bar
${COLOR_GREEN}sv${COLOR_NC}checkout ${COLOR_GRAY}Example: svcheckout http://svn.foo.com/bar
${COLOR_GREEN}sv${COLOR_NC}status
${COLOR_GREEN}sv${COLOR_NC}status${COLOR_GREEN}on${COLOR_NC}server
${COLOR_GREEN}sv${COLOR_NC}add ${COLOR_GRAY}Example: svadd your_file
${COLOR_GREEN}sv${COLOR_NC}add${COLOR_GREEN}all${COLOR_NC} ${COLOR_GRAY}Note: adds all files not in repository [recursively]
${COLOR_GREEN}sv${COLOR_NC}delete ${COLOR_GRAY}Example: svdelete your_file
${COLOR_GREEN}sv${COLOR_NC}diff ${COLOR_GRAY}Example: svdiff your_file
${COLOR_GREEN}sv${COLOR_NC}commit ${COLOR_GRAY}Example: svcommit
${COLOR_GREEN}sv${COLOR_NC}update ${COLOR_GRAY}Example: svupdate
${COLOR_GREEN}sv${COLOR_NC}get${COLOR_GREEN}info${COLOR_NC} ${COLOR_GRAY}Example: svgetinfo your_file
${COLOR_GREEN}sv${COLOR_NC}blame ${COLOR_GRAY}Example: svblame your_file
‘”
Here I wrap each command:
alias sv=’svn –username ${SV_USER}’
alias svimport=’sv import’
alias svcheckout=’sv checkout’
alias svstatus=’sv status’
alias svupdate=’sv update’
alias svstatusonserver=’sv status –show-updates’ # Show status here and on the server
alias svcommit=’sv commit’
alias svadd=’svn add’
alias svaddall=’svn status | grep “^\\?” | awk “{print \\$2}” | xargs svn add’
alias svdelete=’sv delete’
alias svhelp=’svn help’
alias svblame=’sv blame’
alias svdiff=’sv diff’
You may have noticed I added a few commands too, such as svaddall; this isn’t part of standard Subversion. This command, for example, adds all files that aren’t already in the repository.
OS X specific: The following alias allows you to use the FileMerge OS X app for your diffs. You need to create fmdiff and fmresolve, which can be found at this site.
Note: Use diff for command line diff, use fmdiff for gui diff, and svdiff for subversion diff.
alias svdiff=’sv diff –diff-cmd fmdiff’ # OS-X SPECIFIC
Functions
Functions deserve their own article. But basically they are used when an alias isn’t enough. The following is a simple example of a function, it is used to show the both the info and the log of a file in subversion in one command (svgetinfo):
svgetinfo (){
sv info $@
sv log $@
}
All done… finally
Recent Comments