Changing the PS1 on an interactive bash subshell easily

You can use process substitution to essentially make a ~/.bashrc that only exists for the bash -i invocation like so:

 bash --rcfile <(echo "PS1='foo: '") -i

I think it would be better to use env PS1="foo: " /bin/bash --norc -i instead of using the --rcfile option. The environment is preserved, not overwritten by the dot files and the PS1 environment variable is set before entering the shell.

You might also want to think about opening a restricted shell, if the calling program gives extra privs. env PS1="foo: " PATH=$RESTRICTED_PATH /bin/rbash --norc -i for whatever value you want for $RESTRICTED_PATH.

Or have an already prefabricated bashrc file:

if [ -f /etc/bashrc ]; then
    source /etc/bashrc
fi
if [ -f ~/.bashrc ]; then
    source ~/.bashrc
fi
PS1="foo:"
PATH=$RESTRICTED_PATH

And then call with /bin/bash -rcfile ~/.bashrc.appsubshell -i


If you still want the ~/.bashrc to be read and assuming the ~/.bashrc does not set $PROMPT_COMMAND, you could use this trick:

PROMPT_COMMAND='PS1="foo: ";unset PROMPT_COMMAND' bash

Another approach which would work even if your rc files set $PS1 and $PROMPT_COMMAND would be to do (from a zsh/bash/ksh93 shell) something like this:

(
  export IN_FD
  exec {IN_FD}<&0
  echo 'PS1="foo: "; exec <&"$IN_FD" {IN_FD}<&-' | bash -i
)

That is feed the PS1="foo: " via a pipe and then tell bash to switch stdin to the original stdin.

That has the side effect of displaying a prompt and that command line on stderr. You could work around it with:

(
  export IN_FD ERR_FD
  exec {IN_FD}<&0 {ERR_FD}>&2 2> /dev/null
  echo 'PS1="foo: "; exec <&"$IN_FD" {IN_FD}<&- 2>&"$ERR_FD" {ERR_FD}>&-' |
    bash -i
)

Though that has the side effect of hiding the error messages output by your startup files if any.

Tags:

Bash