python 2.7.12 on Linux behaving differently than on Windows

Steve D'Aprano steve+python at
Fri Dec 9 10:26:15 EST 2016

On Fri, 9 Dec 2016 09:34 pm, Marko Rauhamaa wrote:

> Steve D'Aprano <steve+python at>:
>> On Fri, 9 Dec 2016 04:52 pm, Marko Rauhamaa wrote:
>>> In Linux, "." and ".." are taboo.
>> No that's incorrect. It isn't that . and .. are forbidden, but they are
>> reserved: every single directory in Unix file systems have a . and ..
>> directory entry. So they are legitimate directory names -- they're just
>> not names you can use for your own files, as they are already in use.
> Same difference.

Of course they are different.

'\0' (the ASCII null character) is not a legal file name. You can't open a
file with that name, or (more relevant to this point) have a directory with
that name.

'..' and '.' are legal file names, or to be more specific, legal directory
names. You can have directories with those names, and they can appear in

py> os.path.isdir('..')
py> os.path.isdir('\0')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.3/", line 41, in isdir
    st = os.stat(s)
TypeError: embedded NUL character

See the difference?

>>> So is "".
>> That's one way of looking at things... I'm not sure that the empty
>> string counts as a file name. Its more of the LACK of a file name.
>> Besides, that would be ambiguous. Would "/home/steve/" mean my home
>> directory, or the file "" inside my home directory?
> If Python had been the standard shell 

Python isn't a shell.

> when Unix came about, 

Ah, a counter-factual.

> you could  
> have defined pathnames as lists of strings. Then, everything would be
> unambigous and there wouldn't be any taboo or reserved names.

I really don't think so.

So what path does [] represent? How do you distinguish between the root
directory / and no pathname at all in a syntactically correct, unambiguous
manner, using only lists?

What path does [[]] represent? How about [[], []]?

Here's a nice one for you to think about:

L = []; L.append(L)

What path does L represent? How would it be represented in the file system?

What about this "path"? [None, 23, float('NAN'), {}]

What's the difference between ['a', 'b', 'c'] and ['a', ['b', ['c']]] as
path names? If there's no difference, are you concerned at the redundancy?
Is there a canonical form for paths?

How do you represent the current and previous directory in a list without
reserving identifiers for them?

How do you distinguish between '/home/steve' and '/home/steve/' for those
programs that (rightly or wrongly) need to distinguish them?

How do you handle alternate data streams? Or versioning information, for
systems like VMS that track that?

What about file systems where you can have multiple roots? E.g. Windows, C
\file versus D:\file and classic Mac Floppy:file and HardDrive:file?

Do you really imagine that if Python were a shell, and required system
administrators to write things like:

mount ['dev', 'dvd'] ['mount', 'dvd']

instead of

mount /dev/dvd /mount/dvd

that it would have been a success?


> BTW, guile allows *any* characters in an identifier. Even the empty name
> is a valid identifier:
>    > (define #{}# "hello")
>    > #{}#
>    $1 = "hello"
>    (symbol->string '#{}#)
>    $2 = ""
>    > (symbol->string '#{.}#)
>    $4 = "."

And are Guile programs improved by having the empty string as an identify?

When was the last time you were coding and you thought "This program would
be so much easier to understand and maintain if only I could name this the
empty string"?

Does it simplify the process of one programmer talking to another programmer
about an algorithm to be able to use \n\n\n\0\n\n\n as an identifier?

Sometimes more is less.

“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

More information about the Python-list mailing list