My move to Linux in the workplace almost necessarily entails a shell change. I’ve been using tcsh for years, going back to the days before bash added tab completion, if memory serves, but in the last year or so, I’ve been considering a switch to bash for several reasons:
- It’s the default shell on the Mac and most CLI help articles reference bash.
- Every Unix variant I can think of seems to ship with bash as the default shell.
- Some Unix variants don’t even bother to ship with tcsh.
Ubuntu, my distro of choice, is one of those variants that doesn’t ship with tcsh. Yeah, I know I can install tcsh easily enough, but that seems like a recipe for repetition over time as I work on new machines running other distros that may or may not include a tcsh install. For the sake of universal access, I think I’d rather just conform.
This past weekend I began the process of migrating my well-worn, painstakingly accumulated .tcshrc login script to its bash counterpart, .bash_profile. What I’m finding is that it’s not all that simple.
Exhibit A: Prompt Customization
I like to customize my prompt so that it includes my username, the machine’s hostname (minus the domain portion) and a variation on my current working directory. The variation I prefer includes only the last two directories of the working directory preceded by a makeshift ellipsis, if necessary. For example, if I’m investigating the Eclipse installation in my home directory, my prompt might look like this:
But here’s another twist, occasionally I switch contexts to become another user using the su command and, because I want it to be as clear as possible what context I’m working in, I like to bold the username portion. Let’s look at the bold preference first.
With tcsh, it’s a pretty intuitive syntax:
set prompt='%B'`id -nu`'%b&@%m# '
This would display rob@hostname$. The “B…%b” elements delimit the bold formatted portion of the prompt (incidentally, %(technical)`id -nu` runs the id executable to accurately return the runtime context). That’s pretty intuitive, I think. In bash…not so much:
PS1="\[\033[1m\]`id -nu`\[\033[m\]@\h "
Huh? Exactly. I won’t even try to explain. The explanation isn’t the point; the unintuitive syntax is the point.
And what about the second customization, the one where only the last two directories of the current working directory are displayed? Using tcsh, it’s just a minor tweak to the syntax above:
set prompt='%B'`id -nu`'%b@%m [%.02]%# '
Okay, so this isn’t exactly obvious or even intuitive, but at least it’s possible. At this point, I haven’t found any way to do this in bash short of writing a shell script fragment or an awk script within my .bash_profile script.
Exhibit B: Ignore Case in Tab Completion
My immersion in all things Mac have provided me an appreciation for human-readable, mixed case file and directory names. On my Linux desktop, I may be a little more prone to using all lowercase, but I’m hardly religious about it. Hell, even the default home directory structure looks a little Mac-ish with respect to capitalization.
Given that mixed case environment, I don’t want to be bothered with remembering how the path I need is cased. Since I use tab completion excessively, or maybe obsessively, I want the system to find the directory I want without respect to case (I am religious about avoiding like-named directories, of course). Again, using tcsh this is a single line in my .tcshrc file:
set complete = enhance
Doing the same thing in bash doesn’t even involve one of the many bash login scripts (/.profile, /.bash_profile, /.bash_login or /.bashrc). Instead, you have to update a new file, .inputrc with the following line:
set completion-ignore-case on
The syntax makes more sense, but it cost me a lot of Google time to figure out that the directive belongs in the separate file.
I’m not arguing right or wrong or proposing that one is superior to the other. I’m just saying that there are a lot of differences and that the change hasn’t been as smooth as I’d hoped and even assumed that it would be.