How can I protect parentheses passed to a cd command?

52,190

Solution 1

Use single quotes ' around the argument. (This works for any command, not just cd).

cd 'My path with spaces (and parentheses)'

You can't make bash pass the parentheses to cd. Getting the spaces to work at all is a very specialized hack.

Single quotes work around every character except ' itself. Replace single quotes by the 4-character sequence '\''.

cd 'Apostrophe'\''s a pain'

This doesn't work if the directory name begins with a hyphen, because that causes the cd command to interpret the argument as an option. Pass -- before the directory name to avoid this.

See https://unix.stackexchange.com/questions/69144/how-do-i-escape-a-sub-directory-name-with-an-ampersand-in-it/69147#69147 for more details.

Another method is to have the shell read a separate line of text instead of passing the argument on the command line.

Strapakowsky@darkstar ~$ read -r; cd -- "$REPLY"
My path with spaces (and parentheses)
Strapakowsky@darkstar ~/My path with spaces (and parentheses)$ 

Rather than copy-paste manually, you might as well do it programmatically. Install either xclip or xsel.

cd -- "$(xclip -o -selection clipboard)"
cd -- "$(xsel -bo)"

You might make this an alias.

alias cde='cd -- "$(xsel -bo)"'

Solution 2

How to correctly cd to directories with characters like spaces and parentheses in their names:

If your folder name doesn't include a single-quote character ', just enclose it in single quotes:

cd 'My path with spaces (and parentheses)'

If it does include a ', but doesn't include a double quote character ", a backlash \, a backquote ` or a dollar $, enclose it in double quotes:

cd "My path with spaces (and parentheses)"

It's not very common for a file or directory name to contain both single and double quotes. (This is perhaps due to how it's not common for a file or directory name to contain double quotes at all. The only reason I didn't recommend double quotes originally is that, unlike single quotes, double quotes allow the $ to expand environment variables. This would be a problem if your filename contained a $ character followed by text.)

If it contains both, or you just want another method, then you can escape each space and parenthesis manually by inserting a backslash character \ before it:

cd My\ path\ with\ spaces\ \(and parentheses\)

That's annoying, but fortunately, the shell with do it for you, if you type the beginning of the name and press Tab. If there is more than one file or directory name that starts with My, then you might need to type some more to get it to expand. If you press Tab and it doesn't expand you can press Tab again to see a list of files that match what you've typed so far. Then you know how much more you must type to get it to match uniquely and expand.

Alternatively, you could escape the internal quotes. For example, suppose you had a folder called:

Mischa's gardening tips for "home and office"

You can use:

cd Mischa\'s\ gardening\ tips\ for\ \"home\ and\ office\"

But you can also simply use:

cd 'Mischa'\''s gardening tips for "home and office"'

Backslashes aren't special inside single quotes, so we terminate the single-quoted string, append a backslash-protected single quote, and immediately start another single-quoted string, all without any space that would start a separate argument.

Why you probably cannot make cd work the way you wanted it to:

As for getting cd My path with spaces (and parentheses) to work: no, you really cannot do that, because this behavior is not specific to the cd command, it is part of the way running any command works. When a command is run, it is give a list of arguments provided by the user. When the shell sees a space, it knows one argument has just ended and another has just begun. To pass a space as part of an argument it must be quoted in one of the above ways.

You could achieve part of this some of the time--you could make cd My path with spaces work to go into the My path with spaces folder. You could achieve this by writing a shell script that concatenates all its user-provided arguments with spaces. (Then if you wanted you could make cd itself call that script, by creating a shell alias named cd for it; that would take precedence over the shell builtin cd which you currently are ordinarily running.) But:

  • The script would not receive different arguments for My path with spaces and My path with spaces, so cd My path with spaces would fail or enter the wrong folder.

  • You could not do this for the parentheses, because these are used for grouping by the shell such that they are not communicated in any way to a command. Actually, most of the time the shell will simply throw a syntax error (just as you have seen):

    ek@Kip:~$ cd My path with spaces (and parentheses)
    bash: syntax error near unexpected token `('
    

    No matter what you change, that syntax error will continue to occur when that command is given.

I say that you "probably" cannot make this work because there is one way that will--you can make your own shell that behaves as you wish. But this is extremely difficult and it's unlikely that anyone would want to do that, just to make this change. (You could also modify the source code of an existing shell, which is a more practical solution but still requires more effort than most people would want to exert.) Besides that, it's unlikely that cd can accept directory names with arbitrary characters including spaces in them, like it does on Windows.

In case you're wondering why this works on Windows but not in Ubuntu: In Windows, commands are passed the text typed after them as a string of text, and when a command needs to interpret that string as a sequence of separate arguments (which it usually, but not always, does), the code for the command must call a special library function that parses the command-line string. (In a C program, this happens behind the scenes, but still involves using the Windows API.)

Share:
52,190

Related videos on Youtube

Strapakowsky
Author by

Strapakowsky

Updated on September 18, 2022

Comments

  • Strapakowsky
    Strapakowsky over 1 year

    I asked here how to make cd protect spaces. Tab completion is great, but sometimes you paste the path from the clipboard so this is useful.

    The solution breaks with parentheses however. No matter how you try to escape and protect the input it always returns:

    bash: syntax error near unexpected token `('
    

    Is there some way to have it also deal with parentheses? What I want is that when I enter this, it works:

    cd My path with spaces (and parentheses)
    
  • Strapakowsky
    Strapakowsky about 11 years
    The read -r trick is great, but the clipboard trick can be faster with an alias like cde that just cds to the directory you have in your clipboard. I tried to do this, but the alias make the quotes disappear when interpreted. How can I make sure that the alias when run outputs cd 'My path with spaces (and parentheses)', which is then executed?
  • Strapakowsky
    Strapakowsky about 11 years
    Can't all that be solved with a function that parses my command, quotes the string after cd and then pipe it to | sh? This should be doable, but I'm stuck in that whatever I try the interpretation disappears with the quotes.
  • Eliah Kagan
    Eliah Kagan about 11 years
    @Strapakowsky Can you provide more details on exactly what you've done so far? Right now I don't understand why this method would not be subject to all the restrictions I detailed in my answer, that would prevent a shell script (or a function, or an alias) from being able to parse the entire command string at once.
  • h3.
    h3. about 11 years
    @Strapakowsky The easy way is to write a command that doesn't contain single quotes, and put it in single quotes when defining the alias. See my edit. See How do I escape a sub-directory name with an ampersand in it? for more information on quoting.