24

There is plenty of literature about its meaning, the current directory, but I would like to ask about why such thing do exist in first instance.

While CHDIR .. usefulness is obvious, i.e. go to the parent directory, CHDIR . is a bit confusing since it does nothing but switching to the same directory the user is already in.

Does the single dot directory exists purely for architectural symmetry reasons or were there technical reasons back then that made this a necessity?

8
  • 23
    How to copy files to the current directory? Yes, cp path_to_files .
    – Janka
    Nov 2, 2019 at 6:25
  • as usual it might be helpful to add the OS the question is about. Having CHDIR mentioned seams to point to MS-DOS - then again the dot entries are of Unix origin, aren't they?
    – Raffzahn
    Nov 2, 2019 at 11:54
  • 16
    Choosing chdir . as the centre of the argument seems a little odd, because it's a no-op function. Command sets abound with effective no-ops: cat /dev/nul, etc. One useless example does not demonstrate the lack of usefulness. Nov 2, 2019 at 13:29
  • 1
    As a counterpoint, the ur-paper about hierarchical file systems has a parent reference * -- though it's unclear to me after a quick scan whether this is parsing convention or actual directory entry) -- but no self reference. Nov 2, 2019 at 16:27
  • 8
    In some modern remote file systems, cd . actually does have a purpose: it "reconnects" the local filesystem to the remote, while leaving the shell in the same directory. It's useful if you want to keep using a shell instance that has a stale connection. Nov 3, 2019 at 4:12

9 Answers 9

32

It simply makes sense to have a symbol that stands for the current directory. It makes sense for the symbol to be easy to type and to stand out from ordinary directory names. Dot is a pretty good choice. It makes learning a lot easier if the same symbol means the same thing in multiple contexts. consider the following:

chdir .\subdir
copy c:\test\*.* .
start .
chdir .

Only one of these is a no-op. the dot refers to the same thing in all of them, except for the dot that separates the two asterisks.

Next, a side issue. How did dot come to mean the current "location"?

The answer is probably in DDT for the PDP-1, a program written in 1961, give or take a year. DDT allowed interactive debugging of programs written for the PDP-1 computer. In DDT, dot slash meant open the current location for examination and possible alteration.

./  {current contents displayed}  {new contents may be entered}

Now the "current location" meant one 18 bit word in DDT, while it means a directory in commands like CHDIR.

It's likely that dot as a symbol for the current location comes down to DOS from that source. Adaptations of DDT were produced for the PDP-6, PDP-7, and PDP-10.
Bill Gates used PDP-10 DDT while in high school. Unix was first implemented on a PDP-7, where the authors would have been exposed to DDT.

8
  • 2
    I would guess that MS-DOS's usage of '.' came from XENIX (where UNIX got the dot is a separate issue). 1978: MS licenses unix. 1980: first XENIX release. 1981: first PC-DOS release (no directory support). 1983: PC-DOS 2 released (with directory support). also: retrocomputing.stackexchange.com/questions/12048/… Nov 2, 2019 at 13:51
  • I edited my answer to provide the substantive answer first, and then the side issue. I also added a hunch as to how dot got into the world of unix, based on your helpful comment. Thanks. Nov 2, 2019 at 14:29
  • 1
    I'd say the 'dot' notation came from PDP-1 assembler syntax, which is where I assume DDT got it from too. See PDP-1 Macro doc. Nov 2, 2019 at 20:43
  • Macro and DDT were written at about the same time, and it's possible one of them got it from the other. Or maybe they both got the dot symbol from the TX0 world. Nov 2, 2019 at 22:29
  • 1
    My understanding for powershell is that the initial dot is necessary when the context doesn't limit the token to identifying a file. Nov 4, 2019 at 1:55
13

CHDIR . is a bit confusing since CHDIR produces the exact same result and both in fact are pretty much a no-op.

Not really, not even at first sight, as (under MS-DOS) chdir prints out the current directory, while chdir . does not. Of course, this may vary depending on the OS in use. For example under Unix, neither cd . nor cd produce anything but a linefeed.

Still, chdir . and cd . do in fact change the directory, which includes triggering various checks and actions within the OS - like access rights. chdir also isn't a no-op, as it may have additional functions depending on the OS. Under MS-DOS for example, it prints the current path - which is also a visible difference from chdir ..

Does the single dot directory exists purely for architectural symmetry reasons or was there a technical reason back then that made this a necessity?

The reason is still there and it's the same as for the double-dot-entry (..): providing a symbolic name for the current directory. Either entry can be used whenever a directory name is required. Within commands this may arise for two reasons:

  • To name a directory without knowing the actual name

Whenever a command needs a directory as parameter, the dot-entries can be used to specify one. Having them not only simplifies typing, but also allows position independent scripting.

  • To satisfy the need for a positional parameter to not be empty

Unix (and DOS) commands rely on positional parameters. Even if the default value for such a parameter is the current directory, it does need to be present when another positional parameter follows. For example cp <from> <to> would lose its meaning if <from> is simply left empty. Using a single-dot will make it work without having to type the whole path or some weird construction like ../<name>.

In both cases, * can not be used, as it does not specify a (single) directory, but the list of files/directories within an directory.

In addition, as UncleBod reminds, the single-dot-entry is quite necessary to form a full path name to make sure a file from the current directory is executed. When looking up a command Unix searches only within the given search path, unlike MS-DOS, where the actual directory is always searched first.


Adding both symbolic entries to the directories was basically a quick hack to add the feature of a symbolic name for 'actual' and 'parent' directory to each and every path handling without having to implement it with every command.

11
  • 4
    Running a command from current directory if: 1) current directory isn't in the path (considered good practice by some) 2) if you are not sure that the current directory will be the first directory in path where the file can be found
    – UncleBod
    Nov 2, 2019 at 10:26
  • To my understanding the entries in the directories for Unix file systems was essentially required when using inodes, not a hack. Nov 2, 2019 at 10:42
  • @ThorbjørnRavnAndersen Not really. Inodes work on a file level. A directory system doesn't neither need a pointer to itself (As the corresponding inode has already been found and read to get the entry), nor its parent (As again, that has been found prior - and the root directory having a fixed inode). Having both pointers doesn't change anything within the directory structure. It's icing on the top, simplifying handling.
    – Raffzahn
    Nov 2, 2019 at 10:57
  • 4
    "For example under Unix, neither cd . nor cd produce anything but a linefeed." -- they don't produce any output, at least not in any of the Linux and Mac systems I've ever used. (There's a newline at the end of the command line, but it doesn't come from the command itself.) And of course the simple cd changes to the user's home directory, so it's also not a no-op.
    – ilkkachu
    Nov 2, 2019 at 16:08
  • 2
    cd. can be very handy if the current folder has been deleted and replaced with a new folder with the same name. Nov 2, 2019 at 19:28
11

Another use of the dot that I think has not been mentioned is that it allows you to specify what executable to use and tells the OS to not search the PATH. If I type (DOS or Unix)

pdflatex

then the OS will search for an executable named like that, starting with the current directory and then those listed in the PATH variable.

But if you type (in DOS; in Unix you would use the regular slash)

.\pdflatex

then the OS will only search the current directory and ignore other instances of pdflatex that may exist in the PATH.

3
  • IIRC, that is the only way to run a program that has the same name as an internal command in the shell as well (at least in COMMAND.COM: other shells may differ.)
    – ErikF
    Nov 3, 2019 at 6:30
  • 1
    Sure, but I think the argument that we can use dot to make a local pathname, thus bypassing the algorithm that converts a filename to a pathname, exhibits horse-cart inversion. We get to use dot for that purpose because it's already there. The question ultimately s not asking what we can do with dot, but why it exists on disk. Nov 3, 2019 at 20:15
  • 1
    The current directory was removed from the default path many years ago in most unixy systems, because it's a minor security hole: echo 'I haz u' > ls; chmod a+x ls; ls etc.
    – Rich
    Nov 5, 2019 at 2:12
6

The . entry exists in MS-DOS because it was copied from Unix.

In Unix, it serves the purpose of supplying a name to the current working directory. If we want to traverse the current working directory, we need to pass something to the opendir function:

DIR *d = opendir(".");

The dot is also useful for executing programs that are in a relative path. For security reasons, relative paths are not included in PATH by default.

$ cc myprogram.c -o myprogram
$ myprogram
file not found: myprogram
$ ./myprogram
Hello, World
$

The PATH searching rule is that if the command name contains no slashes, then PATH is used, otherwise it is taken as-as. In order to insert a slash into the myprogram path name, we need to put it in front, and then we need a ., otherwise we have the absolute path /myprogram.

All that still doesn't answer the question of why . entries have to actually be in the file system. We can guess here that the reasons is a certain elegance: it avoid special cases elsewhere.

Note that in early versions of Unix, it was the mkdir utility which created both the . and .. entries. (Click the link for mkdir.c source from 1979.) In early Unix, the mknod system call (familiar for creating character and block special files) also created directories. I.e. nodes in the filesystem tree; hence "make node". The mkdir program used mknod to create the directory, and then link to make the . and .. links. Today, making hard links to directories typically is not allowed in Unix-like operating systems, and there is a dedicated mkdir system call.

Essentially, these were conventions established by user space.

If user space didn't create the . link, then to have that convention, the kernel's name lookup routine would've had to implement it as a special case, which the designers might have regarded as an inelegant option.

Of course, when non-Unix filesystems are integrated into Unix, they don't necessarily have a dot entry. But their respective filesystem drivers can simulate the presence of that entry to conform to the convention.

It's also noteworthy that the mkdir.c program is taking advantage of the . being a prefix of ..; it uses strcat to add the dots to a path buffer one at a time as it is making the links.

3
  • 1
    Off-topic: Isn't this line rom mkdir.c a bug: dname[strlen(dname)] = '\0'; ? After we fail to link dot-dot, we need to unlink dot. The line I quote is intended to remove the second dot, but it just overwrites the terminating nul with nul. Needs -1. Nov 4, 2019 at 14:20
  • @another-dave That's right, and there are also no bounds checks for the 128-byte buffers, so you get memory corruption if your paths are too long. I'm sure it's come a long way since then.
    – Jakob
    Nov 5, 2019 at 5:29
  • the reasons is a certain elegance: it avoid special cases elsewhere. - I think this is the reason why it is implemented in the file system - avoids handling it in the kernel code. Apr 1 at 16:20
4

At least in MS-DOS, when a new directory is created, it is first populated with two special entries, .. which points to parent directory where it was created from, and . which points to itself. It is possible that being currently in some directory just means keeping a pointer to a directory, and absolute path name can be get by just following the .. entries until you hit the root where there is no .. entry. Therefore the . and .. entries can actually be handled just like other directory names in the code, as everything is related to the directory you currently are in, and it enables to give the target directory whether it is a parent, current, or sub-directory.

1
  • Funny thing: the root (in DOS FAT at least) doesn’t get these entries, yet using “.” in a path is valid while at the root. So, special handling is needed anyway in path searching routines. This is unavoidable because DOS 2 needed to be able to process disks formatted by DOS 1, and DOS 1 needed to be able to process the root of disks with subdirectories (directories were introduced in DOS 2). I had never noticed this quirk until now. May 14, 2021 at 13:51
2

In many file systems, having the 'dot' (.) directory as referring to the current directory is necessary to determine the name of the current directory.

In UNIX file systems as well as the FAT file systems used in DOS, the names of files and directories are stored as tuples in the parent directory, as opposed to file systems like NTFS where the name is a property of the file itself. If you are not familiar with the file allocation table (FAT) file system, then its structure can be understood as a series of clusters, with a table containing information about which block follows which. Then there are directories, that are basically files containing information about names of their entries along with the index of the first block of data.

Now, to determine the name of the current directory, you need to look into the parent by opening 'dotdot' (..) and looking for the entry that matches the id of the 'dot' (.) directory. That's still how you would do it on inode based modern linux file systems.

-1

I'd venture the opinion that "it's simply the Unix way". From what I'd read, the file system was one of the first parts of the system to be designed. Unix tends to put in the file system things which, on other systems, tend to be elsewhere. For example, devices (and their drivers) appear as special files, where metadata in the inode identifies the actual driver and unit number. You could achieve the same effect without the special files, as for example NT and its offspring do through the Object Manager.

Given that file-centered mindset, it seems a small step to consider that if you want a "self" entry in a directory, actually creating the entry on the disk is the way to go.

From my point of view, building around the file system is a good unification concept. Unix started on the path; Plan 9 (a subsequent system from some of the same people) followed through to a greater degree. The approach provides an underlying consistency to the entire system.

Lest I be accused of being one of the biased "high priests" of Unix mentioned in another answer: I've lost count of the number of OSes I've programmed on, and Unix only puts in a small appearance in that roster. I merely recognize a good idea when I see one.

-2

While CHDIR .. usefulness is obvious, i.e. go to the parent directory, CHDIR . is a bit confusing since it does nothing but switching to the same directory the user is already in.

Sometimes one needs to do a CHDIR . - for example, if the current directory is deleted (by another process, usually) and the recreated, the OS doesn't know where you are until you do a CHDIR .. (From bitter experience in current Linux systems.)

1
  • OS knows exactly where you are in that case - you're in an unlinked directory. When it's "recreated", that's a misnomer: you're talking about a completely different directory that's known by the old name. That said, I know of certain shells that like to keep track of working directory name; they don't like having an unlinked directory as working directory. Nov 4, 2019 at 16:07
-3

The contrarian view is that the use of "." to represent the current directory is not a necessary feature, and is not really a "feature" at all. Rather, it is a legacy of unsophisticated command-line parsers that we simply became stuck with as mostly an accident of history.

All early disk operating systems relied on a command line to interact with the filesystem. There are many conventions that can be used for command line parsers and these range from very simple to quite sophisticated. On this spectrum, the simplest approach is to make all essential parameters be required, and to parse these required parameters positionally. Optional parameters can also be positional (at the end). More advanced command line parsers add possibilities like parameter defaults, flags, named parameters, and positional independence of the arguments. It's akin to the difference in the parameter passing to functions in a simple language like ANSI "C" vs. something with a more advanced parser like Python.

So what was this accident of history? It's just that the OS's that went for the simpler command line parsing conventions ended up being the dominant ones, and therefore the ones we best remember and still use (in the case of Unix derivatives). While MS-DOS was taking over the world, many of us contrarian types were using AmigaDOS, which had a more advanced command line parser that would use the current directory as the default parameter when none was specified. Additionally AmigaDOS supported position independence, named parameters, and other more advanced parsing features. Note how these are actual "features" of the parser, whereas the use of the "." for the current directory is a way to deal with parser simplicity when the parser is not sophisticated enough to choose sensible parameter defaults by itself.

By viewing the "." convention for current directory as a convention necessary for simpler command line parsers, rather than as some "feature" that was consciously developed, it becomes more clear how we ended up using it decades later.

7
  • 2
    I tend to disbelieve this explanation in terms of parsing, since programs need a convenient way to say 'current directory' too. In any case, the parsing explanation does not require '.' to actually be a directory entry, Nov 2, 2019 at 16:35
  • The '.' is just an early convention, as others have justified. The meta-question is why do you need a convention if the current directory is the assumed default, as is done with many other parsers that weren't as popular as DOS-ism & Unix-ism. For programmer libraries, default parameters also works fine, but only when using languages that have more parsing features instead of being minimalist about it. The counter-argument is really only that "minimalism is a feature". That's an oxymoron, even though it can be defended philosophically.
    – Brian H
    Nov 2, 2019 at 16:55
  • 1
    That's the reason that this question is getting so much attention... It easily strokes the religious tendencies of the "high priests" that feel as though Unix must have been handed down on stone tablets...
    – Brian H
    Nov 2, 2019 at 16:59
  • 7
    As for your "parameter is current directory when not specified," say I write a program that, given two directories, tells me what filenames exist in the first that do not exist in the second. If the only way to specify "current directory" is to leave out an argument, you've got a problem because, given only one directory name, is the source or target directory the current directory?
    – cjs
    Nov 3, 2019 at 4:07
  • 2
    Re, "...convention...for simpler command line parsers." Simpler, yes, but command line parsers? No. The syntax of command lines just reflects the underlying structures that the command lines describe. Treating directories like ordinary files makes unix-like file systems simpler. And having each directory contain a designated name that stands for itself simplifies the operating system calls that operate on directories even further. Command lines and command line parsers then are simpler merely because the file structure and the system calls to which they refer are simpler. Nov 4, 2019 at 1:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .