I'm trying to use the Bash parameter expansions to modify the output of a command substitution or another parameter expansion.

The following nested expansions work quite well in Zsh; but result in a "bad substitution" error in Bash:



${$(basename $PWD)//trunk/latest}

the output should be the last folder of the $PWD, replaced by latest when my current directory is trunk

so /home/user/trunk should become latest

Is there a Bash equivalent allowing to chain expansions without relying on variables or pipes? Or do Bash expansions only allows the input to be a string or a plain variable?

3 Answers 3


No, that nesting of substitution operators is unique to zsh.

Note that with zsh like with (t)csh, you can also do ${PWD:t:s/trunk/latest/}.

Though bash also supports those csh history modifiers for history expansion, it doesn't support them for its parameter expansions.

Here with bash, use a temporary variable:

var=${PWD##*/} var=${var//trunk/latest}

Try this with bash:

[[ $PWD =~ .*/(.*) ]] && echo "${BASH_REMATCH[1]//trunk/latest}"

or with one command:

[[ $PWD =~ .*/(.*) && ${BASH_REMATCH[1]//trunk/latest} =~ (.*) ]]

The result is in ${BASH_REMATCH[1]}


do you want...?


I don't see a method to your request. If you want to replace all of $PWD w/ latest - though the best way to do that is to cd to latest.

[ /home/user/trunk = "$PWD" ] && OLDPWD=../latest cd -

...which will take you to latest and print the pathname to stdout. You can get right back where you came from by doing cd - again. You can do the same w/ $CDPATH:

mkdir -p /tmp/{1..5}  ; \
CDPATH=/tmp cd 3; cd -; \
echo "${CDPATH:-empty or unset::}" "$OLDPWD"

empty or unset:: /tmp/3
  • The issue does not lay in the substitution itself, it can be achieve with sed in few steps. But i don't understand why bash refuse to execute subshell, then replace its content like any other string
    – yabuki_joe
    Commented Jan 6, 2016 at 16:07

You must log in to answer this question.

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