24

I'm writing a shell script which parses the path of the current working directory (printing a like of all basenames above the current directory).

So far, I've been using the environment variable PWD to parse the path but I wonder if

  • I can count on PWD to be always set
  • to give the same result on every platform

Would it possibly be better to use the pwd shell-builtin? I need this script to run on as many platforms as possible, so I just wondered...

helpermethod
  • 59,493
  • 71
  • 188
  • 276

5 Answers5

32

POSIX requires $PWD to be set in the following fashion:

PWD  

This variable shall represent an absolute pathname of the current working directory. It shall not contain any components that are dot or dot-dot. The value is set by the cd utility, and by the sh utility during initialization.

So you can rely on that being set – but do note "... an absolute path...", not the absolute path.

bash (at least recent versions) will remember what symlinks you followed when setting $PWD (and the pwd builtin). command pwd (that is, the external command) will not. So you'll get different results there, which might, or might not, be important for you. Use pwd -P if you want a path without symlinks.

Do note that the pwd documentation states:

If an application sets or unsets the value of PWD, the behavior of pwd is unspecified.

So, don't do that :)

In short, there is no winner here. The environment variable will be there in POSIX shells, as will the external command and possibly a built-in too. Choose the one that best fits your need, the important thing being whether you care about symlinks or not.

Mat
  • 202,337
  • 40
  • 393
  • 406
  • 1
    [POSIX](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pwd.html) also says: "If an application sets or unsets the value of PWD , the behavior of pwd is unspecified". Might want to include this in your answer. It clarifies for good that neither choice is to be 'preferred' (except depending on whether or not you want symlinks) – ArjunShankar May 29 '12 at 08:04
  • if current working directory gets removed, pwd command will cause error. $PWD still shows now non-existing dir. – papo Nov 06 '20 at 14:48
4

From that forum article, "$PWD vs `pwd`" which compares AIX 4.2.1, AIX 6, Sparc Solaris 10 and Redhat 5 enterprise with this regard:

  • there is no difference between $PWD and builtin pwd,

  • there is no difference between builtin pwd -P and /usr/bin/pwd.

The former shows working directory with names of symbolic links whereas the latter displays actual path.

The only discrepancy is that external command is in /usr/bin in most systems and /bin in Redhat.

mouviciel
  • 66,855
  • 13
  • 106
  • 140
3

Another point to note is command substitutions are not generally safe on trailing newlines .

This is obviously fairly contrived, but if you're really concerned about safely handling input you should be using "$PWD". See, for example:

$ my_dir=$'/tmp/trailing_newline\n'
$ mkdir -p "$my_dir"
$ cd "$my_dir"
$ pwd
/tmp/trailing_newline

$ printf "%q\n" "$(pwd)" "$PWD"
/tmp/trailing_newline
$'/tmp/trailing_newline\n'
$ cd "$(pwd)"
sh: cd: /tmp/trailing_newline: No such file or directory
$ cd "$PWD"

It is possible to work around the command substitution but it is by no means pretty. You can append a trailing character and then strip it with a parameter expansion:

$ pwd_guarded="$(pwd; printf '#')"
$ pwd_fixed="${pwd_guarded%$'\n'#}"
$ printf "%q\n" "$pwd_fixed"
$'/tmp/trailing_newline\n'
$ cd "$pwd_fixed"

This is particularly ugly because you then also have to strip the newline that pwd adds, which would normally have been stripped by the command substitution. This becomes a total mess if you don't resort to non-POSIX constructs like $'', so basically, just use "$PWD" if you care about these things. Of course it is perfectly reasonable to just not support trailing newlines in directory names.

Izaak van Dongen
  • 2,450
  • 13
  • 23
2

If you know that bash is available and the script is executed with it, PWD is safe.

If, on some systems, only plain sh is available, use pwd.

Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
1

If it were me, I'd use pwd since it is a built-in both for bash and sh. That does not mean they work identically in all respects, but if you are invoking it without options, that shouldn't matter.

CodeClown42
  • 11,194
  • 1
  • 32
  • 67