37

This is merely just a vocabulary question, but which keeps turning around in my head.

It comes from a practice exam from a LPIC preparation book. The correct answer according to the book is that ~/Documents is a relative directory because it is relative to the home directory.

However, this book contains an honourable ratio of typos and mistakes so I cannot take for granted everything which is written there. Here I do not agree because for me ~ acts as a variable expanded by the shell into either the content of the $HOME variable or the current user home directory path (cf. man bash), so the actual path is /home/myuser/Documents which is indeed an absolute directory.

Even Wikipedia, for once, seems of no help to me on this topic (even if it seems to confirm that the book is wrong on this one):

An absolute or full path points to the same location in a file system regardless of the current working directory. To do that, it must contain the root directory.

By contrast, a relative path starts from some given working directory, avoiding the need to provide the full absolute path.

Here again, I do not agree: according to this definition, the path /opt/kde3/bin/../lib which does not depends of the current working directory should be an absolute one, however my current understanding of this matches the book's author making this path a relative one.

A quick web-search is just adding to my frustration, according to Webster Dictionary:

absolute path - A path relative to the root directory. Its first character must be the pathname separator.

So $HOME/Documents, or even just $HOME would not be considered absolute directories? Or does this definition implies variable expansion? What about the shell's ~ character? Is there any reliable definition of relative vs. absolute directory I can find somewhere and am I wrong all of the way?

10
  • 7
    All paths are relative, some of them are just relative only to the root directory /, and those we call absolute. Thus everything what starts from / I would call absolute (even if this is /usr/../etc) and everything else I would call relative (~/Doc, Doc, ../john/Doc, $HOME/...,...). The point is that absolute should work regardless of current working directory or current user. Relative can work only in some specific narrow cases.
    – jimmij
    Commented Aug 8, 2015 at 15:13
  • 6
    The path could expand to a different location depending on who the user is. Having said that, this is still an absolute path, not a relative path, in my opinion. Though I don't think the definitions of absolute and relative path are so precisely defined. This isn't mathematics. This question doesn't really test understanding, imo, and is pointless. Commented Aug 8, 2015 at 15:27
  • 1
    @FaheemMitha: LPIC is a distribution neutral Linux certification. The certification itself seems fine, but this is far from being the case about (at least some) books sold to prepare for this exam as self-study... Commented Aug 8, 2015 at 15:47
  • 2
    @jimmij: "relative" has a specific technical meanings in the context of paths, and using a different English-language sense of the word is bad practice. I totally disagree with calling ~/foo a relative path. What you're getting at is the difference between hard-coding and parameterization. See my answer for more details. Commented Aug 9, 2015 at 6:23
  • 1
    The Webster Dictionary's definitions is correct, but very confusing. However, it implies that strings such as ~/Documents and $HOME/Documents are not paths. They do identify (absolute) paths after expansion, but they are not paths themselves. I think that agrees with how many Unix/Linux users use the term, but no doubt those strings are also called paths themselves. Commented Aug 10, 2015 at 10:27

7 Answers 7

48

This is essentially a question about the definition of terms. So for your purposes, the answer is whatever LPIC wants. But we can come to some conclusions based on technical facts:

If you passed '~/Documents' to a system call, it would look for a directory named exactly ~ in the current directory (and probably fail). So, by the notion of pathnames used by the kernel, this is a relative path — but that's not what we meant.

~ is syntax implemented by the shell (and other programs which imitate it for convenience) which expands it into a real pathname. To illustrate, ~/Documents is approximately the same thing as $HOME/Documents (again, shell syntax). Since $HOME should be an absolute path, the value of $HOME/Documents is also an absolute path. But the text $HOME/Documents or ~/Documents has to be expanded by the shell in order to become the path we mean.

Thus if I wanted to be precise and consistent, I would say that ~/Documents is a fragment of shell-script which expands to an absolute path.

7
  • Of course, the kernel would have no idea what $HOME means, just like it has no idea what ~ means. I do however find the claim that ~ expansion is done by the shell to be dubious; most applications support this, which points toward the C library rather than the shell. Environment variable expansion however is a feature of the shell; you can open ~/somefile.odt in LibreOffice, but not $HOME/somefile.odt, even if LibreOffice was started from a shell within which $HOME is properly set.
    – user
    Commented Aug 8, 2015 at 22:33
  • 6
    You can find it dubious all you want, but it's documented and should be easy to confirm or disprove in C.
    – Useless
    Commented Aug 8, 2015 at 22:47
  • 6
    Other programs implement ~ syntax in imitation of the shell, because it's a useful shortcut. I don't actually know whether there's a library function that does the expansion, but it's definitely something that is done separately from actually using the pathname.
    – Kevin Reid
    Commented Aug 8, 2015 at 23:14
  • 2
    glob and wordexp do tilde expansion among other things.
    – o11c
    Commented Aug 9, 2015 at 3:29
  • 2
    @MichaelKjörling: A few programs implement ~ expansion; most do not. For example, if you type ls -l ~, the ls program never sees the ~ character; it's expanded by the shell before ls is invoked. If you actually pass a ~ to ls, it won't treat it specially; try ls -l '~'` (which will try to list a file named literally ~). Commented Aug 9, 2015 at 7:04
42

If the author was trying to catch you out by talking about that literal string (without shell expansion) as a path, then it's a relative path (mkdir -p './~/Documents'). Otherwise:


It's an absolute path, because resolving it doesn't depend on the process's current working directory. Relative path always means relative to the process's working directory. Or in the case of symlink targets, relative to the location of the symlink. (gcc -> gcc-5.2 vs. gcc -> /usr/bin/gcc-5.2). This matters for NFS-mounts and other cases where you can get to the same symlink via different absolute paths. e.g.

/net/tesla/home/peter/foo -> bar  # always works from other machines

/net/tesla/home/peter/foo -> /home/peter/bar  # references my home dir on the local machine, not tesla.

Debian will sometimes install symlinks to ../../doc/whatever/whatever, instead of an absolute symlink target, so it works when NFS mounted somewhere else, or when looking at a chroot without chroot(8)ing into it.

Every Unix process has its own cwd. The pwd command exists just to print it.

see: http://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html for more about changing directories with POSIX system calls.


As everyone else has said, ~ is expanded by the shell before the path is used for anything. Using ~/bin/myprog in a shell script will make it work differently for different users. The difference between ~/bin/foo and /home/peter/bin/foo is that one of them has hard-coded the location, while the other has parameterized it. It's an error (IMO) to call the ~ version a relative path.

Talking about things being "relative to an environment variable" is just confusing. It's bad practice to use different English-language meanings of terms that have specific technical meanings in the context you're using them in.

On a broken system, with HOME=a/relative/path, ~/foo would expand to a relative path. This would not be a usable setup at all.

3
  • 3
    Thank you for this answer, it seems to be the most comprehensive one to me. I have also the impression that the author wrongly mixed up the notion of canonical path into this (which the author do not mention anywhere). /opt/kde3/bin/../lib for instance is wrongly classified as a relative path: it is an absolute path but is not the canonical one. As you said, this just makes everything confusing, so thanks for your clarification and the info related to NFS :) ! Commented Aug 9, 2015 at 9:07
  • 1
    I have to conclude that writing a test-prep book is not a lot of fun, and that people who just use Unix or GNU/Linux for their everyday computing aren't the ones writing those books. That example of a calling a non-canononical path relative seems really bad and obvious to me. man7.org/linux/man-pages/man3/realpath.3.html (and realpath(1)) do both things: canonicalize and make absolute (as well as follow symlinks), so possibly some confusion crept in there. Commented Aug 9, 2015 at 9:23
  • 2
    Still, those are just ordinary everyday concepts for me. I think it'd be weird to have a piece of paper that said I knew them... But good luck getting your piece of paper, @WhiteWinterWolf, to show to all the people that like to look at pieces of paper. :) Commented Aug 9, 2015 at 9:25
15

If your $HOME is /home/white/, ~/Documents (same as $HOME/Documents) is expanded by the shell (see here for an explanation) to /home/white/Documents, which is an absolute path.

A relative path is one that does not start with a / (after shell expansion), like ../Documents or foo/bar

Some old shells don't expand ~ (the way bash, tcsh, zsh, etc. ... do); they would see ~/Documents as a relative path starting with ~; but you usually don't have directory name like ~ (but you might create one with mkdir '~', which I don't recommend).

1
  • you should mention which shells dont expand ~
    – Alex Jones
    Commented Aug 12, 2015 at 13:49
3

An absolute path starts at / (what it refers to is fixed), a relative path starts at the current directory (and so what it refers to changes as the current directory changes). Most shells use ~ at the beginning as an abbreviation for the absolute path to the home directory of the current user, i.e., ~/Documents is the directory Documents in the home of the current user, regardless of what the current directory might be. So it is an absolute path.

1

The path could expand to a different location depending on who the user is. Having said that, this is still an absolute path, not a relative path, in my opinion. However, I don't think the definitions of absolute and relative path are so precisely defined. This isn't mathematics. This question doesn't really test understanding, in my opinion, and is pointless.

1
1

The use of the ~/ at the beginning makes the path absolute since (by any definition) being able to find documents does not depend on where you currently are. However the expansion is done by the shell, not the kernel, so if you are using a shell that does not recognise this syntax ( such as /bin/sh, the original Bourne shell, not the bash alias ), you will be out of luck.

Interestingly, if you use ~root/ rather than ~/, the optimisation of reading $HOME typically does not apply and it will always resolve to an absolute if /etc/passwd is correct.

-1

The book seems to be taking the view that an absolute path is any path beginning with a /, and a relative path is anything else.

You might view .. and $HOME as similar types of tokens. Both need to be substituted, for a path component, before the path resolves to an absolute path.

1
  • 3
    How is .. anything like $HOME? .. can be at the start of a path passed directly to a system call, no shell expansion required. Such a path is not an absolute path; it's still relative to the process cwd or symlink location. Unless the author was trying to catch you out by talking about that literal string (without shell expansion) as a path. I think you're trying to make excuses for the book, but I'm more inclined to just say it's wrong and not let things get muddled. Commented Aug 9, 2015 at 8:59

You must log in to answer this question.

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