First let’s get rid of the directory display altogether because we will create a new function to do that in a moment.
Setting
PS1="$> " s
I located a path 16 dirs deep using this command.
$> ls /*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/ -d
And I changed to that directory.
$> cd /home/tester/usr32/src/installers/ftl-2011-09-23-a/usr32/src/ftl-2011-09-
23/extras/image-formats/libjpeg-6b-rs/test/lib/src/opt/
Normally, the prompt would display that entire string cluttering up the display considerably, even without the normal prompt prefix stuff.
But in fact I do want to know where I am, but how do I get the directory to show and still get the clean input prompt?
First let’s generate a tiny app to simply limit the length of a path printout.
[The “//” things are comment markers, that stuff isn’t part of the code.]
// print_pwd.c Usage: print_pwd [max_len]
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h> // getenv()
// Insert ellipses in paths to limit length to DEFAULT_MAX_LEN
// or user supplied max_len, for use in the command propmt. No
// usage notes just this source file.
#define DEFAULT_MAX_LEN 64
// returns a temporary pointer to the possibly trimmed path.
// inserts ellipses in middle of the string, no newline appended.
const char* trim_pwd(int max_len)
{
int len_half = max_len / 2;
static char dir[2048]; // a really really really long path :-)
strcpy(dir, getenv("PWD"));
int len_total = strlen(dir);
if(len_total > max_len)
{
strcpy(dir + len_half - 1, "...");
strcat(dir, dir+len_total-len_half - 2);
}
return dir;
}
int main(int argc, char** argv)
{
long max_len = 0;
if(argc == 2)
sscanf(argv[1], "%d", &max_len);
if(!max_len)
max_len = DEFAULT_MAX_LEN;
printf("%s", trim_pwd(max_len));
return 0;
}
This will compile it.
gcc -O2 -s print_pwd.c -o print_pwd
and then put it in your HOME/bin folder so it’s in the path as all files
in that folder are by default.
[This is not the same as the internal trim function that only shows you the end of the path and has no control over the number of chars shown.]
Now let’s create a bash command to use that C executabl to make a customized prompt.
[It’s best to do this in bash because it is easier to modify later and our C code didn’t add any newlines or anything else for the same reason.]
Start with this (in bash). You can run it in a script for testing or you can live dangerously and copy it directly into your HOME/.bashrc file. (to test in a script type ‘source scriptname’ and it will attempt to interpret any text file!)
# less obnoxious prompt for digging deep into long paths
# (for development, etc.)
prompt_command()
{
# 64 chars of path should do it. And just in case,
# suppress error messages to avoid confusion
local ps=`print_pwd 64 **2>/dev/null**`
printf "
PWD:%s]
" $ps
}
PROMPT_COMMAND=prompt_command
PS1="\$> "
The “2>/dev/null” sends the output of stderr to nowhere. We don’t want to see errors if something goes wrong because we won’t know what is causing the error messages.
The PROMPT_COMMAND is a bash internal variable which we point to our bash function which uses the C code to trim the path to any size we like.
After the code above was copied into HOME/.bashrc and I typed ‘bash’ again on the commandline to start a new bash session with the new .bashrc loaded.
And here’s what it looked like. Remember we are 16 directories below root and the path is over a hundred and fifty characters long, normally wrapping at least once and possibly twice in a normal bash prompt.
PWD:[/home/tester/usr32/src/installe…ats/libjpeg-6b-rs/test/lib/src/opt]
$> ls
jmemdosa.asm jmemdos.c jmemmac.cPWD:[/home/tester/usr32/src/installe…ats/libjpeg-6b-rs/test/lib/src/opt]
$> [And my cursor is here ready for another command]
As you can see the bash function has added two newlines (
). One is to separate the PWD display from the output of the previous command and the other to put the “$>” command prompt on a new line so our own typing doesn’t wrap randomly and get confusing to read.
If you have konqueror installed you can begin discovering all the fun stuff you can do with prompts by typing
konqueror man:bash
And fishing around in the internal variables sections.