28

I downloaded lessn to my webserver and unzipped it.

It contains a folder named -. I assumed I know how to deal with that, but I don't.

I tried cd -- -, but that doesn't have the desired effect. Using quotes doesn't seem to affect it either. I put slashes all over the place, to no avail.

What's the proper way to change into this folder?

4 Answers4

35

You want to avoid it from being a parameter, thus we try to prepend something to it. The current directory can be accessed with ., thus the subfolder - can be accessed alternatively with ./-.

cd ./-

The reason that cd -- - doesn't work is because this is implemented differently if you compare rm (see man rm) to cd (see man bash or man cd), cd has a different interpretation which sees - as a parameter (see man bash or man cd).

It should also be noted that cd is a shell builtin function, as can be read in this answer:

cd is not an external command - it is a shell builtin function. It runs in the context of the current shell, and not, as external commands do, in a fork/exec'd context as a separate process.

There is an external cd command, but it does something entirely different.

This explains why the implementation is different, as Bash and Coreutils are two different things.

Let's just suppose you wouldn't believe this, how do we confirm that? Use which and type.

 $ which cd && type cd
which: no cd in (/usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/x86_64-pc-linux-gnu/gcc-bin/4.7.2:/usr/games/bin
cd is a shell builtin
 $ which rm && type rm
/bin/rm
/bin/rm is /bin/rm

See man which for more information, and man bash or man type for type

Tamara Wijsman
  • 740
  • 4
  • 10
24

A minus (a.k.a. dash) alone is not an option, but an operand (i.e. an argument that isn't an option). Because of this, putting -- before it has no effect. The dash is an operand in cd - and still an operand in cd -- -. Like other standard utilities, cd treats an operand as an operand regardless of whether there's -- before it.

The cd command assigns a special meaning to the operand -. Anything else is a directory to switch to. cd -- -a switches to the directory called -a, because -a is not special as an operand and the -- prevents cd from treating it as an option. This doesn't work for - alone which isn't an option.

Putting quotes around - isn't going to help, since that would eventually pass the operand - anyway.

Your only recourse is therefore to find another way of expressing the same idea, i.e. another name for the same directory. Fortunately, there's an easy one: if you add ./ before a relative file name, it still means the same file. The ./ does make a difference which is irrelevant in our case: CDPATH is not consulted when the directory name begins with /, ./ or ../. Thus:

cd ./-

Another way, since - is a directory, is to add a / after it. Adding a / at the end of a file name ensures that the file is treated as a directory (in particular, the command will operate on the directory itself and not on the symlink if the file is a symbolic link to a directory), but otherwise makes no difference. Thus:

cd -- -/

Writing -/ is suggested by the completion code, by the way, but in bash it only actually works with -- before it, bash doesn't have a special case for cd -/ (zsh does).

  • That blows my mind, I actually tried cd -- -/, but due to having run the equivalent of cd - right before that, the directory actually did not exist and I interpreted it as another failed attempt. – Oliver Salzburg Oct 27 '12 at 00:03
5

Qualifying with path is one option.

cd ./-
iruvar
  • 16,725
2

These would also work:

cd ~/'-'

or

cd ~/"-"