84

I encountered BASEDIR=$(pwd) in a script.

Are there any advantages or disadvantages over using BASEDIR="$PWD", other than maybe, that $PWD could be overwritten?

4
  • 5
    some info at unix.stackexchange.com/a/79621 Dec 12, 2014 at 11:19
  • @StéphaneChazelas Very interesting write up. I'm only halfway through and will continue, but as far as I understood it, it's better to use $(pwd), because $PWD can become outdated in certain circumstances.
    – Minix
    Dec 12, 2014 at 11:51
  • 3
    only in some shells (not bash, dash, zsh or ksh93 for instance) will pwd potentially give you less stale information than $PWD in some corner cases. $(pwd) on the other hand doesn't work if the current directory ends in newline characters, means forking a process (except in ksh93) and use extra resources. My view is use $PWD of $(pwd -P), it's not worth using $(pwd). Dec 12, 2014 at 11:59
  • 2
    at the bottom there stephane mentions using cd -P -- "$dir". if there is any doubt about the value of $PWD you can always cd -P . first. this may also be beneficial in that you also get whatever $PWD was before that in $OLDPWD and so can compare them afterward - and the next cd ...; cd - sequence will be sure to bring you back to where you are now.
    – mikeserv
    Dec 12, 2014 at 12:57

2 Answers 2

100

If bash encounters $(pwd) it will execute the command pwd and replace $(pwd) with this command's output. $PWDis a variable that is almost always set. pwd is a builtin shell command since a long time.

So $PWD will fail if this variable is not set and $(pwd) will fail if you are using a shell that does not support the $() construct which is to my experience pretty often the case. So I would use $PWD.

As every nerd I have my own shell scripting tutorial

5
  • 8
    I was under the impression that the `command` syntax was undesirable and $(command) is to be preferred. As far as I know the latter is POSIX compliant, but I'm not 100% sure.
    – Minix
    Dec 12, 2014 at 11:51
  • 7
    @Minix The $() is indeed specified by POSIX so outside the pre POSIX /bin/sh available on Solaris 10 and older and csh derived shells, I doubt many other mainstream shells lack that feature.
    – jlliagre
    Dec 12, 2014 at 11:55
  • @Minix: Here is a recent question on this site that illustrates one problem with using backticks instead of $()
    – PM 2Ring
    Dec 12, 2014 at 12:48
  • 1
    correct, instead of $() you could use backticks, but this will not be cascadable so I did not mention it Dec 12, 2014 at 19:23
  • 1
    Nice minimap on your tutorial.... Mar 31, 2016 at 3:30
17

It should also be mentioned that $PWD is desirable because of its performance. As a shell variable, it can be resolved almost instantly. $(pwd) is a bit more confusing. If you inspect man 1 bulitin on a system with Bash, you'll see that pwd is a built-in command, which may lead you to believe that it will be just as fast as accessing a variable. However, the $() construct always launches a new subshell (a new process) to run its contents, regardless of what's inside. The same thing goes for backticks. Indeed, when I benchmark it:

echo 'Benchmarking $(pwd)...'
time (for i in {1..1000}; do echo $(pwd) > /dev/null; done)
echo 'Benchmarking $PWD...'
time (for i in {1..1000}; do echo $PWD > /dev/null; done)

I get 1.52 seconds for the $(pwd) call and 0.018 seconds for $PWD. Unnecessary launching of subshells, as well as any other extraneous processes, should be avoided whenever possible. They're much more expensive than function calls that you may be used to in other languages.

3
  • That's an interesting take on it, but I don't know if I am concerned about performance on my shell scripts. I also wonder how the performance would change, if the pwd changes in between querying it.
    – Minix
    Sep 9, 2018 at 19:30
  • 1
    @Minix I modified my script to have the loop body be echo $PWD; pushd ..; echo $PWD; popd (with additional >/dev/null after each statement), and it takes 0.05 seconds. I then removed the echo statements (only pushd/popd) and it took 0.03. So the time per echo $PWD was still 0.01 seconds or so. I did something similar with $(pwd), and it took 2.2 seconds for each loop, so 1.1 seconds per $(pwd) call. Sep 10, 2018 at 1:26
  • Not to be too picky, but I can imagine, that the computation, that would replace $PWD would be done in the background before the evaluation of the echo statements. But clearly, accessing $PWD is still significantly faster, so if compatibility is not a concern, this is definitely a reason to pick one over the other. Thanks for the work in testing this so thoroughly. :)
    – Minix
    Sep 10, 2018 at 10:37

You must log in to answer this question.

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