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?
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?
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}.
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.
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.
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 typedls, 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.
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.
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 ..
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...)
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.
No one seems to have explicitly mentioned the basic premise of Unix-like systems1:
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.