What are ./ and ../ directories?

57,869

Solution 1

Every directory on a Unix system (and probably every other system too) contains at least two directory entries. These are . (current directory) and .. (parent directory). In the case of the root directory, these point to the same place, but with any other directory, they are different. You can see this for yourself using the stat, pwd and cd commands (on Linux):

$ cd /
$ stat . .. bin sbin | grep Inode
Device: 802h/2050d      Inode: 2           Links: 27
Device: 802h/2050d      Inode: 2           Links: 27
Device: 802h/2050d      Inode: 548865      Links: 2
Device: 802h/2050d      Inode: 2670593     Links: 2
$ pwd
/
$ cd ..
$ pwd
/
$

Notice that bin and sbin each has two links to it. One is the directory entry in the root directory, and the other is the . entry inside that directory.

Using ls with a pipe to wc -l is a simple trick to count the number of lines in ls' output. The assumption is that each file or directory will occupy exactly one line in the output. GNU ls will, when the output is a non-terminal, do this automatically; others might need the -1 option to turn on the behavior explicitly. wc -l simply counts and outputs the number of lines (-l) in its input.

The problem with that approach is that in Linux and on the file systems traditionally used on Linux, file and directory names (they are really one and the same in this regard) are allowed to contain newline characters. In the presence of those, either method falls apart -- those entries will be counted as two or more entries when in reality they are one.

As long as you are using GNU ls, have no directory entries with names containing newline characters, and have no odd aliases for ls (for example, ls -a), both will output the count of files and directories in the current (or specified) directory. For most people, this is good enough, but it is not valid in the general case.

If you need to handle unusual characters (primarily newlines) in directory entry names properly, I suggest using ls's -b option to escape them. ls -1bA will print each directory entry name on its own line, escape unusual characters (so each directory entry will be seen as one), including any dotfiles and -directories. Tack on wc -l for a complete command line of ls -1bA | wc -l which will report the number of files and directories in the current directory (but ignore . and ..; that's the difference between -a and -A), but not descend into any subdirectories. If you don't want any dotfiles to be counted towards the total, simply omit the -A parameter to ls.

Solution 2

To answer the question in the subject:

When a directory B is created in Unix, it is added as a new entry to another directory A (its parent directory), and in B, two entries are added: one called . as a hard link to itself, and one called .. as a hard link to A.

Those are the only hard links to directories allowed (though some older versions of some Unices did also allow arbitrary links).

that's why with most file systems (btrfs being a notable exception), the number of links of a directory is an indication of how many subdirectories it has (accounting for their .. entries).

When you're renaming/moving a directory, if it's to the same directory (under a different name), only the name entry in A is changed. B's . and .. is not affected. But if you move it do a different directory, then .. in B will change. That explains why you can rename a directory on which you don't have write access (assuming you have write access to the parent directory) only as long as you don't move it to another directory (otherwise the need to change the .. entry prevents you from moving it).

Beware though: /a/b/../c might not be the same as /a/c because /a/b might be a symbolic link to some other directory.

An exception to that is when that path is given to the cd command to some shells. Those cds treat .. logically ignoring the .. entries in directories. A reason why you often see cd -P in properly written scripts, to disable that feature that could otherwise cause confusion and inconsistencies.

To count the number of entries in the current directory excluding . and .. with bash, you can do:

shopt -s nullglob dotglob
set -- *
echo "$#"

With zsh:

f=(*(ND))
echo $#f

Portably:

find . ! -name . -prune -print | grep -c /

Solution 3

I'm not a great Linux expert, but I know Linux (used to be administrator 16 years ago, on Slackware :) good old time

the ./ and ../ directories it's simple: . is current directory, .. is previous directory (in the tree of pwd -local directory command-

If it counts them, I reckon they add 2 to the total of listing, not really go recursively and count the directory below the current one, and also count again the current directory (.) :))

So basically I think it adds the value 2 to already count(files) in the current directory.

Anyone correct me if I'm wrong.

I'm just posting to help out and seen that noone answered this question here, they might be busy. But just experiment and see if you have 10 files and get count of 12 then that's it.

Share:
57,869

Related videos on Youtube

Adam
Author by

Adam

Updated on September 18, 2022

Comments

  • Adam
    Adam almost 2 years

    Simple question, but I'm not sure where to look and google doesn't respond to periods and slashes.

    I'm just trying to count the # of files & directories in the current directory (not including subfolders/files) and was trying to differentiate ls -1 | wc -l and ls | wc -l since they seem identical. A site I was looking at said "Keep in mind that this is also counting the ./ and ../ directories." regarding the one with ls -1, and I'm not sure if that means it includes the directories before or something (which I don't want), but it didn't seem to do that from testing.

    Could someone confirm which one of those would be most adequate for counting # of files & directories in the current directory only (not sub) and what they mean by ./ and ../ directories?

    • vonbrand
      vonbrand over 11 years
      The "Keep in mind that this is also counting the ./ and ../ directories" is wrong (unless it is a typo for "." and "..".
  • schaiba
    schaiba over 11 years
    Yes, Adrian is correct : . is the current dir and .. is the directory immediately above in the hierarchy.
  • Bonsi Scott
    Bonsi Scott over 11 years
    .. does not always refer to the previous directory in the tree: in "/" .. refers to the current directory as well.
  • Adrian Tanase
    Adrian Tanase over 11 years
    because you might be in / root of the filesystem ?
  • Adam
    Adam over 11 years
    If it adds two to the # of files in a directory why am I getting the correct answer when testing it in terminal on osx? e.g. a directory with 6 files or folders will output 6, not 8 when I do ls | wc -1
  • Stéphane Chazelas
    Stéphane Chazelas over 11 years
    @Adam, ls doesn't list hidden files. You need ls -A to get the same as those. IF you don't want to count the hidden files, take off the dotglob (for bash) or D (for zsh) or add a ! -name '.*' before -print for find.
  • Adam
    Adam over 11 years
    I realized that it's because they're including hidden files (namely .ds_store), but I still don't see how ls | wc -l includes . and .. when I get the right answer, as opposed to the right answer + 2.
  • Adam
    Adam over 11 years
    Yea, I just noticed this after actually listing the files. Do you know then why ls | wc -l still gives me the right answer and excludes hidden files, . & ..?
  • Adam
    Adam over 11 years
    Both -a and -A include hidden files as well which I've realized I want to avoid, so at most I'd do ls -b | wc -l, but this does give me the right answer. Is the line I copy and pasted regarding this command incorrect? If it was correct, shouldn't I be getting an output of 8 when there are 6 files or folders in a directory?
  • Stéphane Chazelas
    Stéphane Chazelas over 11 years
    Adam, in your directory, you have ., .. and another file whose name starts with . which is not listed by ls but would be by ls -A. So ls | wc -l doesn't give you the correct answer because it is not counting that hidden file.
  • Adam
    Adam over 11 years
    Sorry, I meant to state that I don't want it to count hidden files, but am I right that ls | wc -l does exclude . and .., which would make the statement I copy and pasted in the original post incorrect?
  • Stéphane Chazelas
    Stéphane Chazelas over 11 years
    Yes, . and .. are hidden files since they start with a .. There's even a legend that explains that dotfiles are hidden by accident as an early implementation of ls was meant to exclude only . and .., but there was a bug that caused it to exclude any file starting with .. ls | wc -l doesn't work if filenames contain newline characters.
  • Adam
    Adam over 11 years
    Oh, of course they're hidden, thanks for the help!
  • michael
    michael over 11 years
    @Adam yes, that will probably do the trick ("ls -b | wc -l"); you can also use the "-1" (dash + number one) which forces a listing in a single column instead of all on a single line, but that happens anyway when piping to another command. So (imho) I'd leave it as "ls -1b | wc -l" ; and to "test", run "ls -1b" and count the number of lines, then run "ls -1b | wc -l" and verify the results. (That's how to debug/test pipes.)
  • vonbrand
    vonbrand over 11 years
    @Sardathrion, that FAQ is quite misleading. The Unix filesystem conventions aren't "strange"; where they are common it is the other system picking them up. But OK. Then it says that the "file command uses magic numbers to identify ...", which is wrong: It uses a lot of heuristics too. Not very reliable in my book.
  • Sardathrion - against SE abuse
    Sardathrion - against SE abuse over 11 years
    @vonbrand: fair enough, link deleted. I just skimmed it and it seemed fine. I know I found one that was good but now cannot remember where it was.
  • schily
    schily almost 6 years
    You are mistaken: . and .. are historic artefacts from UNIX in the 1970s and result from a time when there was no mkdir() system call yet. Not all filesystems have them and they are not even needed nor required by POSIX.
  • roaima
    roaima almost 6 years
    @schily POSIX 4.13 defines . and ..
  • schily
    schily almost 6 years
    NO: POSIX just defined what happens when you specify . or .. - it does not require them to be present. You quoted the path name resolution rules, that describes what happens....
  • Manuel Jordan
    Manuel Jordan over 2 years
    (1) About "When you're renaming/moving a directory, if it's to the same directory (under a different name), only the name entry in A is changed" - Ok it has sense - a child of A has changed its own name - (2) but about - "But if you move it do a different directory, then .. in B will change" - it has sense because B would be within C now and therefore B has other parent - so why A was not updated/changed too? -Because A being a parent and if was removed a child directory/file of A, should be updated too, right? -
  • Manuel Jordan
    Manuel Jordan over 2 years
    Therefore if B changes its name A is updated, but if B is moved to C why A was not updated? - I am assuming A has a track of its children?