16

If I run ls -a

user@users-MacBook-Pro:~$ ls -a
.           ..

I get . and .. (current directory and parent directory?)

Is there a reason why they show up after ls -a, do they do anything interesting?

Jens
  • 1,752
  • 4
  • 18
  • 36
Margo Oka
  • 341
  • 23
    it is unclear what you are asking, since you already know what they represent – jsotola Feb 19 '20 at 00:54
  • 4
    Maybe I mean to ask why they show up when you ls -a. Like is there a point to them showing up there? They don't seem to be adding anything useful. – Margo Oka Feb 19 '20 at 01:01
  • 5
    Could you [edit] your question and clarify what you're asking? As jsotola said you already know what these are, and the -a option is clearly documented in man ls as "do not ignore entries starting with .", so what is the question? They appear because you are using an option specifically designed to make them appear. – terdon Feb 20 '20 at 14:15
  • 5
    You are aware that they actually exist on disk in the folder and therefore should show up? – Thorbjørn Ravn Andersen Feb 20 '20 at 23:57
  • Try it on the root directory / – jsejcksn Feb 21 '20 at 12:53
  • @jsejcksn Nothing different in the root directory. Just the inodes are the same, but they are not part of -a output. – Jens Feb 21 '20 at 15:24

9 Answers9

67

Because -a means show all files. It is useful when combined with -l. As to why show those useless files when not using -l, because of consistency, and because Unix does not try to double guess what is good for you.

There is an option -A (for at least GNU ls) that excludes these two (.., and .).

Interestingly the idea of hidden files in Unix came about by a bug in ls where it was trying to hide these two files. To make the code simple the original implementation only checked the first character. People used this to hide files, it then became a feature, and the -a option was added to show the hidden files. Later someone was wondering, the same as you, why . and .. are shown, we know they are there. The -A option was born.

Note: Unix has a much looser meaning of file than you may have.
FILE ⊇ {normal-file, directory, named-pipe, unix-socket, symbolic-link, devices}.

44

Like is there a point to them showing up there?

They show the ownership and permissions. That is often the most important thing to check when you have two users and one is saying they cannot see the other person's file that they were expecting to.

  • 1
    You can check the properties of a directory by just writing the name out on the command line (ls -ld /some/dir, or even ls -ld . if you need to point at the current directory without using its name). There's really no need for -a to list them out just for that. – ilkkachu Feb 19 '20 at 15:12
  • 2
    @ilkkachu: sure, but if you don't want to see . and .., use ls -A (--almost-all) which is otherwise the same as ls -a. (Other comments say that option's documented by POSIX.) – Peter Cordes Feb 19 '20 at 19:58
  • Also to add you can use this to see the date/time modified of current and parent directory – QuickishFM Feb 20 '20 at 09:33
  • 1
    But in the original ls -a they give zero information! With -l option, yes. But then, with perms, owners, time on two lines: why not give also the names: people (not me;) have $PWD in the prompt, because ls -dl . only shows a dot, and you don't want to bother with pwd just for that. –  Feb 20 '20 at 16:19
  • @PeterCordes, err, yeah, sure, we can use that now. But I understand it didn't exist originally, and I don't really see any reason why ls -a couldn't have hidden . and .. from the start. Being able to see their permissions on each and every ls -a doesn't sound that useful to me, since we know they're there, and can check the permissions with ls -d .. directly if required. They're not an interesting answer to "what files have we here", which is what plain ls or ls -a (without a file argument) is mostly for. – ilkkachu Feb 21 '20 at 08:54
  • @ilkkachu: That's fair. ls -a --sort=none (aka -U) is perhaps a more interesting or relevant use-case, to see where those entries fall in the raw filesystem's directory listing order. (Or the at least the kernel's readdir order). Or just to remind you that they're there, and every program that does a readdir on the directory will see them. And neither of those are what this answer proposes, so I don't find it super convincing either. – Peter Cordes Feb 21 '20 at 08:59
  • @ilkkachu -l description says "use long listing format". I would not expect ls to show more files wihen using -l. -l states that it only changes the way in which the listed files are shown. – Giacomo Alzetta Feb 21 '20 at 09:24
  • @GiacomoAlzetta, no, me neither. But you need -l to actually view the permissions. I'm not sure if I mistyped some of the options at some point – ilkkachu Feb 21 '20 at 11:28
8

As shown in https://ss64.com/bash/ls.html when you add the -a parameter to ls
you get all entries, even those which begin with .; they are considered to be hidden entries, and not shown with a simple ls.

K7AAY
  • 3,816
  • 4
  • 23
  • 39
7

This ls option requires to show all files with ls -a...

But the physical existence of . and .. in most filesystems is an artefact from the 1970s, when computers have been very tiny and people tried to find implementations that need only a small code size. This resulted in making hard links to the current directory and to the parent directory.

Since more than 30 years this is seen as a mistake.

In fact, UNOS (the first UNIX clone from 1980) did not have . and .., my WOFS (the first copy on write filesystem) and ZFS do not have them as well.

What is required by POSIX is just to handle dir/. and dir/.. the expected way, when passed to syscalls that handle filenames.

Unfortunately, most software today is still written badly and gets into problems when these entries are missing, this is why ZFS emulates the existence....

As a result, it is unspecified whether ls -a prints lines for . and ... This depends on the filesystem. If you are on a filesystem that does not include physical entries for . and .. and that does not pretend to have them (like ZFS), you need to call: ls -ld . ..

BTW: POSIX decided recently that echo .* is no longer required to include . and .., even when they physically exist. Once all shells behave this way, this will be a big win.

schily
  • 19,173
  • 2
    While this is interesting background, it seems to imply that if they weren't physical entries in the file system, you'd never want ls to show them. But as another answer points out, the combination ls -al is useful for showing the permissions of the current and parent directories, which would otherwise require running something like ls -l ..; ls -l ../.. and looking for the relevant names. – IMSoP Feb 19 '20 at 14:36
  • Correct, I updated the answer. ls -a does not grant output for . or ... – schily Feb 19 '20 at 14:47
  • 1
    “Not required” and “forbidden” are two different things. The former implies that it is allowed, which implies no motivation to change the behavior everyone is accustomed to. – WGroleau Feb 20 '20 at 16:38
  • This is not how POSIX works.We first permit it in the next version of the standard. Then we may require it in the version after the next. This will be in 10 years. – schily Feb 20 '20 at 20:48
7

Is there a reason why they show up after ls -a?

I'd wager a guess it's just a historical accident, like so many things are.


According to a story by Rob Pike, "hidden" files (dotfiles) were created by something of an accident:

Long ago, as the design of the Unix file system was being worked out, the entries . and .. appeared, to make navigation easier. I'm not sure but I believe .. went in during the Version 2 rewrite, when the file system became hierarchical (it had a very different structure early on). When one typed ls, however, these files appeared, so either Ken or Dennis added a simple test to the program. It was in assembler then, but the code in question was equivalent to something like this:

if (name[0] == '.') continue;

This statement was a little shorter than what it should have been, which is

if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) continue;

but hey, it was easy.

Two things resulted.

[...] Second, and much worse, the idea of a “hidden” or “dot” file was created. As a consequence, more lazy programmers started dropping files into everyone's home directory.

Based on that, it doesn't seem far fetched to guess that ls -a was added then to show the dotfiles created by those lazy programmers. And the simple implementation for that would be just disable the above test in turn, resulting in . and .. showing, again.

Regardless of the history, showing them is the behaviour specified in the standard now:

-a
Write out all directory entries, including those whose names begin with a <period> ( '.' ).

But there's also ls -A to do the slightly saner thing. I don't know how much newer that one is:

-A
Write out all directory entries, including those whose names begin with a <period> ( '.' ) but excluding the entries dot and dot-dot (if they exist).


Do they do anything interesting?

Listing them with plain ls isn't very interesting.

But looking for e.g. . in /path/subdir gives the same inode as looking for subdir in /path. The ownership and permissions of the directory control who can access files there, so that information might be nice to have available through ., too. However, one can always do ls -ld . or ls -ld /path/subdir if they need the properties of the directory itself.

ilkkachu
  • 138,973
  • That story sounds very much like a fable / moral story, where the facts take a backseat to the overall "message". You will already find ls -a (with the same meaning as today) in the unix manual from from 11/3/1971 (page 67) –  Feb 20 '20 at 00:54
  • "Version 2 rewrite" is not 2nd Edition, probably. Pike can't be hallucinating about a non-hierarchical epoch. 1st Ed. has mkdir, and it directly mentiones the "standard entries": DESCRIPTION mkdir creates directory dirname. The standard entries "."and ".." are made automatically. But there was a time before . and .. --- when the fs was very diefferent, and not hierarchical. –  Feb 20 '20 at 12:59
  • @UncleBilly, I never claimed to know if the story is true -- I couldn't, since I wasn't there. (Also, that was originally posted on Google+, which doesn't work any more, so I couldn't link to the original either.) But true or fable, it doesn't seem implausible that an original implementation was excessively simple, and then things just got stuck at that. In other words, I suppose it comes down to "because it always worked like that" or equivalent. – ilkkachu Feb 20 '20 at 14:05
  • Nope, the file system had directories (it was "hierarchical") from the very beginning, according to 1 of the 2 people who, unlike Rob Pike, were there at the time (but who unfortunately is no longer here with us). According to the same, it didn't have paths tho -- to access a file in another directory you had to create a hard link in the current directory. –  Feb 21 '20 at 06:54
  • And that, combined with the fact that a dir listing was printed on paper, gives the astute reader enough hints both for why . and .. exists in the 1st place and for why people had to use "hidden" files instead of stashing them in a separate directory. No need for ridiculous mystical-romantic stories about historical accidents. –  Feb 21 '20 at 06:56
  • @UncleBilly 's link has this: "This scheme rendered subdirectories sufficiently hard to use as to make them unused in practice." I think that explains Pike's story well (he is just not very precise). sufficiently hard to use as to... LOL, so there is a limit to user-unfriendliness? –  Feb 21 '20 at 07:23
  • @UncleBilly, mm. I'm still not sure if that tells why ls -a had to show them at the time, instead of working like ls -A. (Them existing doesn't mean they always need to be shown, especially if they're always there anyway.) But yeah, maybe you should post that as an answer of your own? – ilkkachu Feb 21 '20 at 08:50
  • @ilkkachu fwiw, it was "fixed" in Unix version 7 to have ls omit just the . and .., not all the files which start with .. But as everybody knows, BSD is actually derived from Unix version 6, and SysV also soon killed that "fix" too --and it, just like other "improvements", like the boundary preserving pipes from Unix version > 8 (or 9?), didn't made it into Unix, but into plan9. "maybe you should post that as an answer of your own?" No, I should not. –  Feb 21 '20 at 16:09
  • @UncleBilly, in bold? why not? did I miss something (other than the history, that is) – ilkkachu Feb 21 '20 at 16:26
4

In Unix (folklore has it that by mistake) file/directory names starting with . weren't shown by ls (because names . and .. had been reserved for "this directory" and "parent of this directory", and showing them was considered useless clutter). So using that quirk people started using names like .profile or .something-or-other-rc (the RC is from Run Command, startup file name for yet another long defunct system) for files (and directories) that were "uninteresting". Thus ls -a(show all), and of course it'll show . and ..

vonbrand
  • 18,253
  • +1 for mentioning what the files actually do. I was looking to see if someone had mentioned that, and was going to post the answer if it hadn't already been done. – Charlie Feb 22 '20 at 01:10
2

as the design of the Unix file system was being worked out, the entries . and .. appeared, to make navigation easier

No answer seems to see any use in these entries in the first place. They somehow stem from the hierarchical linked list. "Easy navigation": not with ls, but with a C program using readdir(3) or so.

I believe .. went in during the Version 2 rewrite, when the file system became hierarchical


Is there a reason why they show up after ls -a, Do they do anything interesting?

A) Yes (historical/technical reasons) B) Yes, unless you find cd .. uninteresting. (Or clicking on (pseudo)file .. in a graphical file browser)

(OK, they don't have to show up to be used...that's why it's an option and there is also -A)


Even find does it in an empty dir:

]# find
.

Like that I know: find did find something: nothing.


]# stat  . .. |grep Device
Device: 36h/54d         Inode: 154051      Links: 6
Device: 803h/2051d      Inode: 393219      Links: 26
]# cd /
]# stat  . .. |grep Device
Device: 803h/2051d      Inode: 2           Links: 18
Device: 803h/2051d      Inode: 2           Links: 18

This defines the top of the hierachy. The direntries of . and .. are identical in the top dir /. And if you don't realize it, a cd .. is just like cd .. I don't get a message, it just works/fails silently.


Only the fields d_name and (as an XSI extension) d_ino are specified in POSIX.1. Other than Linux, the d_type field is available mainly only on BSD systems.

struct dirent {
           ino_t          d_ino;       /* Inode number */
           off_t          d_off;       /* Not an offset; see below */
           unsigned short d_reclen;    /* Length of this record */
           unsigned char  d_type;      /* Type of file; not supported
                                          by all filesystem types */
           char           d_name[256]; /* Null-terminated filename */
       };

The readdir() function returns [a pointer to] a dirent structure representing the next directory entry in the directory stream pointed to by dirp.

Without a type field, you (ls) would have to look at the inode's content before it can tell file or dir or pipe. And without the . and .., you would have to store these inodes in a variable.


This is how these entries can simplify navigation, for the script and the user. Choice "1" does it with the current directory, pretending . is contained in it, as a dir.

]# select ans in $(ls -af); do ls -l $ans; done
1) .
2) ..
3) child3
4) child2
5) child1
#? 1
total 0
drwxr-xr-x 2 root root 40 Feb 21 07:36 child1
drwxr-xr-x 2 root root 60 Feb 21 07:40 child2
drwxr-xr-x 2 root root 60 Feb 21 07:40 child3
#? 2   
total 0
drwxr-xr-x 5 root root 100 Feb 21 07:36 myself
drwxr-xr-x 2 root root  40 Feb 21 07:37 sibling1
drwxr-xr-x 2 root root  40 Feb 21 07:37 sibling2
#? 3
total 0
-rw-r--r-- 1 root root 0 Feb 21 07:40 f.b
#? 4
total 0
-rw-r--r-- 1 root root 0 Feb 21 07:40 f.a
#? 5
total 0

(It would be more interesting if it cds and then lists the new dir as a select again, and so on...)

0

Is there a reason why they show up after ls -a, do they do anything interesting?

Well, they show up after ls -a because that is the function of the -a switch to ls. You asked ls to show you files beginning with a dot, and so it did. I'm afraid there isn't a better answer; that's what -a is for.

The interesting thing they do is allow relative path specification. You can specify a file location relative to the current default, rather than as an absolute path from root. This is very useful as well as being interesting.

0

No one seems to have explicitly mentioned the basic premise of Unix-like systems1:

Everything is a file.

This includes directories.

Since ls -a lists all files and directories are files, it stands that . and .. would be included.

"Do they do anything interesting?"

Yes, they do. They give you handy references; . represents the current directory and .. represents the parent directory. This allows you to do stuff like mv /file/elsewhere . and cd ... Of course, this is pedantry and you probably already knew this. :)


1 Although @ctrl-alt-delor's answer does imply it.