Going to directory using bash variables doesn't work when directory names have spaces

Short answer: see BashFAQ #050 ("I'm trying to put a command in a variable, but the complex cases always fail!").

Long answer: when bash parses a command, it parses quotes before it replaces variables; it never goes back and re-parses quotes in the values of variables, so they wind up not doing anything useful. Using echo to check the command is completely misleading because it shows the command after it's been parsed; if you want to see what's really being executed use either set -x to have the shell print commands as they're executed, or use printf "%q " $dir; echo instead of plain echo.

If you want to store a complex command (i.e. one with spaces or other special characters in the "words"), you need to put it in an array instead of a simple text variable, and then expand it with the idiom `"${array[@]}", like this:

dir=(cd "/cygdrive/c/Program Files/")
"${dir[@]}"

Now, if the purpose is to make an easy-to-type shorthand, this is clearly not the way to go. Use a shell alias or function instead:

alias dir='cd "/cygdrive/c/Program Files/"'
dir

or

dir() { cd "/cygdrive/c/Program Files/"; }
dir

When bash expands $dir, it only performs word splitting and globbing on it. Word splitting produces three words: cd, "/cygdrive/c/Program and Files/". Then the command to execute is cd with two arguments; cd only looks at its first argument, "/cygdrive/c/Program, which is not an existing directory.

If you want to perform full shell evaluation on the content of a variable, use eval:

eval "$dir"

Note that you need the double quotes around $dir, otherwise word splitting would first be performed, then eval would concatenate its arguments with spaces. This would happen to work here, but would go bad in general (e.g. if there were two consecutive spaces in a file name).

However, a string is not the right way to store a shell command that you want to execute. Unless you have an unusual requirement, you should be using a function instead:

dir () {
  cd "/cygdrive/c/Program Files/"
}

If you are really interested in typing $dir to switch to a particular directory and this isn't just a simple example, since bash 4, put shopt -s autocd in your .bashrc and set

dir="/cygdrive/c/Program Files/"

after which you can type just "/cygdrive/c/Program Files/" or "$dir" at the shell prompt to switch to that directory. You still need the double quotes around $dir; if you don't like that, use zsh instead of bash.