Why doesn’t cd..
work in Unix & Linux?
Unix shells treat a lot of non-alphanumeric characters (e.g., @_+-{}:,./~
)
as if they were letters,
so you could have commands called a@
, b_
, c+
, d-
, etc.
So when the shell sees cd..
, it treats it as a four-letter word,
no different from cdef
or cd56
,
and so it looks for a command called cd..
.1
It doesn’t break it into two words
just because d
is a letter and .
isn’t
(the way CMD does; see below).
______________
1 As pointed out by Bodo, you can define an alias
(or a shell function (or a shell script)) called cd..
.
Of course it’s probably a bad idea to write a shell script called cd..
(or cdanything
),
because a shell script can’t cause the shell that calls it
to change directory.
Why does cd..
work in CMD?
The rules for how CMD parses commands
seem to be complex and not well documented.
- Wikibooks says:
The parsing of a command line into a sequence of commands is complex,
and varies subtly from command interpreter to command interpreter.
- David Deley says that, in Windows, “Everyone Parses Differently”:
You'll get different results if you pass a command line to ShowParams.exe
(written in C/C++), ShowParams.vbs (VBScript), or ShowParams.bat (batch file)…
- How does the Windows Command Interpreter (CMD.EXE) parse scripts?
(on Stack Overflow) contains extensive, detailed answers
to the titular question.
… but (in about an hour’s worth of searching) I couldn’t find anything
that specifically addresses this issue of how CMD determines
what the command is
(i.e., what we would call argv[0]
in a C program in Unix).
I’ve done some testing / experimentation (on Windows 7).
One pattern I’ve observed is that, after a first tokenization pass
(breaking the command line at spaces
and high-precedence characters like <
, >
, &
, |
, ,
and /
),
CMD looks at the first word on the command line,
and breaks it apart at certain other non-alphanumeric characters
(including .
, +
, =
, and \
).
If the word up to the first such non-alphanumeric character
is a builtin command that doesn’t take arguments,
then that command is executed.
For example, cls.
, cls..
, cls.abc
, cls.a.b.c
, cls.exe
, cls=
, cls=abc
, cls+
, cls+abc
, cls\
, cls\abc
, and many more variations,
act like just plain cls
and clear the screen.
Ditto for pause
.
These seem, at first, to be exceptions to the above:
cls/
and cls/a/b/c
give an error message.
cls/?
gives a help message.
pause/
and pause/a/b/c
simply pause
(i.e., they act like just plain pause
).
pause/?
gives a help message, says “Press any key to continue . . .”,
but doesn’t wait for you to press a key.
(This is a bug.)
But the above are consistent with the idea
that CMD breaks things into tokens at /
characters.
cls/
behaves the same as cls /
, for example.
echo
is special case:
echo on
turns the echo on.
echo off
turns the echo off.
- Just plain
echo
reports the state of the echo flag.
- But, if
echo
is immediately followed by a non-alphanumeric character
(like ,
, .
or /
), then that character is ignored,
but special processing for the rest of the command gets disabled.
So, if you want to print the word “on” or “off”,
use echo.on
or echo.off
,
and, to print a blank line, use echo.
.
And so echo..
acts like echo .
[sic].
- TL;DR
In other cases, CMD seems to look up to the last dot
(or group of dots),
and if that substring is a builtin command,
it interprets it as that builtin command.
So cd..
, dir..
, type..\filename.txt
and copy..\filename newname
all act like there was a space before the first dot.
But this works only for builtins;
for example, calc..
and find..
get the “… is not recognized
as an internal or external command, operable program or batch file.” error.
So, for some fun examples:
- If you have a program called
abcd.efg.exe
, you can run it by typing abcd.efg
.
But if it’s called cd.efg.exe
, then cd.efg
fails,
because it’s parsed as cd .efg
.
You would have to type cd.efg.exe
.
- Similarly,
if you have a subdirectory called
abcd
in the current directory,
and a program called efg.exe
in that subdirectory,
you can run it by typing abcd\efg
.
But if the subdirectory is called cd
, then cd\efg
fails,
because it’s parsed as cd \efg
.
You would have to type cd\efg.exe
.
my-random-command
andmy-random-command..
command
andcmd
, fundamentally wrong in a few of them. As I wrote in a comment to one, Unix and Linux is really not the place for a full explanation of these programs. The question is wrong, too, inasmuch as "well" is not the word to use here. I am on record on the subject elsewhere, as is Rex Conn. Given that IBM and Microsoft tacitly discouraged this syntax, with the railway diagrams in the OS/2 doco forcmd
not permitting it, it seems likely that no author ofcommand
,cmd
, or a replacement for the same would say "well" here.