I use tcsh. I'd like to have my prompt formatting (coloring/highlighting) change based on the directory I'm in, or other critical aspects of my environment.

I'm not enough of a shell hacker to know how to do this.

Ownership of Current Directory

If I'm in one of "my" directories (i.e., I am owner of the current working directory), then it should have normal appearance. But if I'm in someone else's directory (I do a lot of support and cd to others' working areas), then I want the prompt to look clearly different.

This is to remind me to not type impolite commands in others' directories. (think make clobber or p4 sync, etc.)

Critical Environment Variable Setting

Another important piece of information for my environment is whether a certain environment variable is set, call it SWDEV. If SWDEV is not set, then my scripts and flows come from their default location. But if this variable is set, then it's taken as a new root location for my scripts and flows, with behaviors changing according to the scripts at that location.

It's important to be reminded of the setting of this variable, lest I expect "normal" behavior but instead absentmindedly run code from the new location.

3 Answers 3


Well, if an external script is an acceptable solution, you could do something like this:

#!/usr/bin/env perl 
use Cwd;
my $cwd=getcwd();
$cwd =~ /$ENV{HOME}/ ? 
             print "$cwd % " : 
             print "%{\033[1;31m%}CAREFUL\\\!%{\033[0m%} $cwd % ";

Save that somewhere in your $PATH as make_prompt.pl and make it executable. And then, in your ~/.tcshrc :

alias precmd 'set prompt="`make_prompt.pl`"'

This will result in:

                     enter image description here

You can also add more conditions to change the prompt in specific ways in different directories:

#!/usr/bin/env perl 
use Cwd;
my $cwd=getcwd();

## Here are some colors to choose from
my $red="%{\033[1;31m%}";
my $green="%{\033[0;32m%}";
my $yellow="%{\033[1;33m%}";
my $blue="%{\033[1;34m%}";
my $magenta="%{\033[1;35m%}";
my $cyan="%{\033[1;36m%}";
my $white="%{\033[0;37m%}";
## This resets the color, you need it after each color command
my $end="%{\033[0m%}";

## If you are in $HOME or one of its sub dirs, print a green prompt
if($cwd =~ /$ENV{HOME}/){
   print "$green$cwd$end % ";
## If you are in /usr or one of its sub dirs, print a red prompt
elsif($cwd=~ /\/usr/){
   print "$red$cwd$end % ";
## If you are in /etc or one of its sub dirs, print a blue prompt
    print "$blue$cwd$end % ";
## If you're in /root. As you can see, colors can be combined
    print $red . "OY\\! You're not allowed in here\\!" . 
          $end . $magenta . " $cwd$end % ";

## For wherever else, just print a plain prompt
else {
    print "$cwd % ";
  • @illuminÉ thanks, it was a typo, it should work now. Note the backticks around the perl script's name (theyŕe not very visible).
    – terdon
    Feb 6, 2014 at 18:10
  • @illuminÉ see updated answer. I added a version of the script with some more options. You can add as many elsif blocks as you wish.
    – terdon
    Feb 8, 2014 at 14:19
  • Your solutions were inspiring and enabling. That was fun! Shell prompts are always about detail. Thank you for the contribution!
    – user44370
    Feb 11, 2014 at 3:40
  • The real trick here is the precmd. You can do anything you want in a shell function, then use the function as the precmd. You don't need an external script. As long as the script takes to run, your prompt will be delayed by that amount of time. Handling everything natively within the shell will reduce this latency.
    – bahamat
    Feb 11, 2014 at 22:23
  • @bahamat absolutely, yes. I just don't know [t]csh syntax and since the OP specified that an external script is acceptable I thought I'd suggest one.
    – terdon
    Feb 12, 2014 at 4:48

I didn't figure out how to do this natively in shell (tcsh), but I did solve the problem using a Perl script.

With a Perl script, you can have logic as sophisticated as you want to check whether you own the $cwd, what environment variables are set, etc. Then, have the script print the prompt string you'd like.

tcsh has a special precmd alias that is executed each time before the prompt is printed. So, having a Perl script "formatPrompt.pl"


use strict;
use warnings;

use Cwd;
# "SWDEV" is an env var special to our environment. Want to be reminded in the prompt of its setting.
use Env qw(SWDEV prompt);

my $prompt = '%U{%m}%~%u> ';
my $prefix = '';

if (defined $SWDEV) {
    # set a prompt prefix if special env var is set. use "Boldface" highlighting.
    $prefix = "%Bspecial env var SWDEV=$SWDEV%b\\n";
if (! -o getcwd) {
    # change the highlighting of the prompt if not your dir.
    $prompt = '%U{%m}-->%~<--%u> ';
$prompt = $prefix . $prompt;
print $prompt;

exit 0;

and an alias defined such

% alias precmd
set prompt="`perl /home/source/perl/formatPrompt.pl`"

can produce

{o-xterm-62}~> setenv SWDEV "/some/special/env/var/value"
special env var SWDEV=/some/special/env/var/value
{o-xterm-62}~> cd /usr
special env var SWDEV=/some/special/env/var/value
{o-xterm-62}-->/usr<--> unsetenv SWDEV
{o-xterm-62}-->/usr<--> cd ~

(Note that if SWDEV is set, its value is printed, and that the cwd is surrounded by -->cwd<-- if the dir is not owned by the user. Try other prompt highlighting such as %S%~%s, also.)

enter image description here

  • There is another feature of the script that I neglected to describe. Besides changing the prompt based on whether I own cwd, it also changes the prompt based on the setting of a particular environment variable that is significant in our environment, "SWDEV" in my example. If "SWDEV" is set, "something different" happens that depends on the var's value. That's why I print this in the prompt as a reminder. In trying to explain, I can't think of a good example of this in a generic Unix environment -- it's just that this var is significant for us. Feb 11, 2014 at 2:11
  • You're welcome! Now I understand what this was about concretely. Thank you for taking the time to explain that and update the script! That was really interesting and fun! Cheers!:)
    – user44370
    Feb 15, 2014 at 1:14

For fun I provide another prototype, based on what I've seen the others do here, using simple if statements; make_prompt:


set     red="%{\033[1;31m%}"
set   green="%{\033[1;32m%}"
set  yellow="%{\033[1;33m%}"
set    blue="%{\033[1;34m%}"
set magenta="%{\033[1;35m%}"
set    cyan="%{\033[1;36m%}"
set   white="%{\033[0;37m%}"
set     end="%{\033[0m%}" 

if ("$dirstack[1]" == "/") then
  echo " ${blue}r${magenta}o${cyan}o${green}t${end} "
else if ("$dirstack[1]" =~ "/home/thisguy*") then
  echo " ${yellow}Watch this guy out\\!${end} "
else if ("$dirstack[1]" =~ "/hom*") then
  echo " ${red}Be mindful of the home dir\\!${end} "
else if ("$dirstack[1]" =~ "/usr*") then
  echo " ${magenta}You're in /usr now\\!${end} "
else if ("$dirstack[1]" =~ "/etc*") then
  echo " ${green}-=etc=-${end} "

With the bit that goes in .tcshrc, opting to use rprompt instead of prompt to automatically align the information to the right:

alias precmd 'set rprompt="`if "$?" == 0 echo "\(ok\)"``if "$?" == 1  echo "\(err\)"``if ("$?" != 0 && "$?" != 1) echo "\($?\)"``make_prompt`"'

Also added is a simple indication of the exit status of the last command (ok = 0, err = 1, $? for anything else).

Limitation is that a specific order is required (from the specific to the general) when making custom messages in the script for directories that are objects within others i.e. /home/thisguy vs. /home here.

enter image description here

  • I can't colorize the exit status because I can't introduce the color sequences in alias precmd, however hard I try. Why not do it in the script? I don't know if it's me (a beginner) but tcsh won't go through a second if/endif block in that context of precmd executing the script - only the first if/endif block gets processed and the other is just ignored?! Also, the space after the $(end) in the script is required to stop colors from leaking. Indeed if the color stopping is the last item with no space, it is ignored (%{string%} cannot be the last in prompt). But overall it's not bad. Cheers!
    – user44370
    Feb 9, 2014 at 18:14
  • The dirstack array was used to make it more tcsh-ish. I had intended for the script to not print its stuff every time; I wanted to push the last dir used with pushd to second position in stack then compare it, and not print if it's same, but the precmd framework has impacts... so it's beyond me. Finally I found exploring this and this was insightful. Also this wonderfully amazing document.
    – user44370
    Feb 9, 2014 at 18:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .