bashcygwincd

How to cd into a directory with space in the name?


I'm attempting to get into the directory /cygdrive/c/Users/my dir/Documents:

$ DOCS="/cygdrive/c/Users/my\ dir/Documents"

$ echo $DOCS
/cygdrive/c/Users/my\ dir/Documents

$ cd $DOCS
-bash: cd: /cygdrive/c/Users/my\: No such file or directory

$ cd /cygdrive/c/Users/my\ dir/Documents
(success)

When I manually type it in, the backspace does its escape character thing, but not when I use parameter expansion with the variable DOCS.

I tried other variations such as no backslash.

$ DOCS=/cygdrive/c/Users\ dir/Documents

$ echo $DOCS
/cygdrive/c/Users/my dir/Documents

$ cd $DOCS
-bash: cd: /cygdrive/c/Users/my: No such file or directory

or

$ DOCS="/cygdrive/c/Users/my dir/Documents"

$ echo $DOCS
/cygdrive/c/Users/my dir/Documents

$ cd $DOCS
-bash: cd: /cygdrive/c/Users/my: No such file or directory

The same happens for $HOME:

$ echo $HOME
/home/my dir

cd $HOME doesn't work either. Quotes must be put around it.

What the heck:

$ DOCS="\"/cygdrive/c/Users/my dir/Documents\""

$ echo $DOCS
"/cygdrive/c/Users/my dir/Documents"

$ cd $DOCS
-bash: cd: "/cygdrive/c/Users/my: No such file or directory

Solution

  • $ cd "$DOCS"
    

    You need to quote "$DOCS" to prevent spaces from being parsed as word separators. More often than not, variable references should be quoted.

    Note that $HOME would have the same problem. The issue is coming from when the shell evaluates variable references; it's nothing to do with what variables you use or how you assign to them. It's the expansion that needs to be quoted.

    $ echo $HOME
    /home/my dir
    

    This is deceptive. echo is actually echoing the two strings /home/my and dir. If you use cd or ls you'll see how it's actually working.

    $ ls $HOME
    ls: cannot access /home/my: No such file or directory
    ls: cannot access dir: No such file or directory
    $ cd $HOME
    bash: cd: /home/my: No such file or directory
    $ cd "$HOME"
    <success!>
    

    Can I ask why it works when I manually type it in but not in a variable?

    Great question! Let's examine the commands you typed:

    $ DOCS="\"/cygdrive/c/Users/my dir/Documents\""
    $ echo $DOCS
    "/cygdrive/c/Users/my dir/Documents"
    $ cd $DOCS
    -bash: cd: "/cygdrive/c/Users/my: No such file or directory
    

    The reason this doesn't work is because Bash doesn't parse quotes inside variable expansions. It does perform word splitting, so whitespace in unquoted variable expansions is taken as word separators. It doesn't parse quotes in any way, meaning you can't put double quotes inside a variable to override word splitting.

    $ cd $DOCS
    

    Because of this, cd is passed two parameters. As far as cd knows it looks like you wrote:

    $ cd '"/cygdrive/c/Users/my' 'dir/Documents"'
    

    Two parameters, with double quotes intact.