Bash – How to cd from parent1/suba/subb to parent2/suba/subb without listing subdirectories

bashcd-command

I have multiple parent directories with the same file structure beneath them.

Example:

parent1/suba/subb/
parent2/suba/subb/

When I am in parent1/suba/subb, I would like to change to parent2/suba/subb without doing something like cd ../../../parent2/suba/subb. How can I do this without listing all the subdirectories and ../s?

Best Answer

You can use the PWD variable and parameter expansion constructs to quickly apply a text transformation to the current directory.

cd ${PWD/parent1/parent2}

This doesn't have to be exactly a path component, it can be any substring. For example, if the paths are literally parent1 and parent2, and there is no character 1 further left in the path, you can use cd ${PWD/1/2}. The search string can contain several path components, but then you need to escape the slash. For example, to go from ~/checkout/trunk/doc/frobnicator/widget to ~/checkout/bugfix/src/frobnicator/widget, you can use cd ${PWD/trunk\/doc/bugfix/src}. More precisely, the parent1 part is a shell wildcard pattern, so you can write something like cd ${PWD/tr*c/bugfix/src}.

In zsh, you can use the shorter syntax cd parent1 parent2. Again, you can replace any substring in the path (here, this is exactly a substring, not a wildcard pattern).

You can implement a similar function in bash.

cd () {
  local options
  options=()
  while [[ $1 = -[!-]* ]]; do options+=("$1"); shift; done
  if (($# == 2)); then
    builtin cd "${options[@]}" "${PWD/$1/$2}"
  else
    builtin cd "${options[@]}" "$@"
  fi
}

Zsh provides completion for the second argument. Implementing this in bash is left as an exercise for the reader.