Eko3alpha Eko3alpha - 2 months ago 20
Bash Question

different evaluation of pwd in ~/.bash_profile alias depending on type of quote

This is on OSX El Capitan, but also happens in my Ubuntu aliases as well.

I ran into an issue with an alias I created to pass the working directory to a docker container.

this wont work (always passes ~/Users/username for $(pwd) no matter what directory I'm in):

alias phpqa="docker run --rm -u $UID -v $(pwd):/app eko3alpha/docker-phpqa"


works:

alias phpqa='docker run --rm -u $UID -v $(pwd):/app eko3alpha/docker-phpqa'


However I started getting unexpected errors in my script when the wrong path was being passed in. So I did an experiment. I added both these aliases into my ~/.bash_profile.

alias getpath="echo $(pwd)"
alias getpath2='echo $(pwd)'


I logged off and then logged back in.

Change directory:

$ cd /Users/username/correct/path/to/project


Execute both aliases:

$ getpath
/Users/username

$ getpath2
/Users/username/correct/path/to/project


the alias with the double quotes always returns the users home directory while the alias with single quotes returns the current directory. Can someone explain why that is?

Answer

The alias definition is parsed like any other command. Inside double quotes, variable substitutions like $UID and command substitutions like $(pwd) are expanded. Inside single quotes, nothing is expanded: the only special character is a single quote which terminates the single-quoted literal.

alias phpqa="docker run --rm -u $UID -v $(pwd):/app eko3alpha/docker-phpqa"

Assuming that your user ID is 1000 and the current directory is your home directory /Users/username at the time your .bash_profile is read, this defines the alias phpqa with the expansion docker run --rm -u 1000 -v /Users/username:/app eko3alpha/docker-phpqa.

alias phpqa='docker run --rm -u $UID -v $(pwd):/app eko3alpha/docker-phpqa'

This defines the alias phpqa with the expansion docker run --rm -u $UID -v $(pwd):/app eko3alpha/docker-phpqa. Each time the alias is expanded, it's replaced by the corresponding string and that string is subject to the usual shell parsing rule. So each time the alias is used, the current value of the variable UID is used and the command pwd is executed.

The correct definition of this alias would be

alias phpqa='docker run --rm -u "$UID" -v "$PWD:/app" eko3alpha/docker-phpqa'

Always use double quotes around variable and command substitutions unless you know that you need to omit them. $PWD and $(pwd) are equivalent (the shell tracks the current directory in the variable PWD).

Alternatively, forget about quoting (except for double quotes around substitutions) and use a function.

phpqa () {
  docker run --rm -u "$UID" -v "$PWD:/app" eko3alpha/docker-phpqa
}