This bash file running on Mac terminal failed to change the directory. Rather reporting it does not exist when it actually does. Any thing I did wrong?

#!/usr/bin/env bash
set -e
read name
  • Try replacing ~ with $HOME. – DopeGhoti Dec 29 '16 at 22:34

There are two points:

  • Problems with tilde expansion
  • Problems with sourcing vs. executing.

For the tilde part, a very recent question at superuser was about the same issue (https://superuser.com/questions/1161493/why-bash-script-wont-extend-bashrc/1161496#1161496)

The tilde is expanded before the variable, so the cd cannot find the path. To overcome this, lead the command with eval as such:


Unfortunately, when you execute the script (I mean, if it is chmod'ed to "+x", calling the path), you will see that the $PWD does not change in the "current shell". However if you add such a line at the end of the script


You will see that, ls is executed at the new working directory. How come?

The answer is here (https://superuser.com/questions/176783/what-is-the-difference-between-executing-a-bash-script-and-sourcing-a-bash-scrip#176788)

Short answer: sourcing will run the commands in the current shell process. executing will run the commands in a new shell process. still confused? then please continue reading the long answer.

Shortly, to change the $PWD at current shell, you should "source" the script as such:

source /path/to/script


. /path/to/script

A third point: If you don't want to mess with source or ., you can define an alias in your ~/.bashrc (https://stackoverflow.com/questions/752525/run-bash-script-as-source-without-source-command):

alias mycmd="source mycmd.sh"

  • 1
    I tend to always use $HOME rather than ~ in scripts. Looks better too, in my opinion. – Kusalananda Dec 29 '16 at 22:49

you can use tilda '~' you just need to have turned on the proper bash expansion key

set -x

or use either full path '/Volumes/Swap/Apps/...'

use bashrc to set env shortcuts like

export LocalApps=/Users/me/Applications
export SysApps=/Applications

i wouldn't use eval

if you just want to suck in a string from the command line you don't need to use read just grab the arg

if [[ $# -eq 1 ]]; then
    #check if it's directory
    if [[ -d $name ]] ; then
      #do stuff here
      echo 'bomb'

instead of 'cd-ing' to a directory learn how to use ~+, ~-, pushd and popd, many times you don't need to actually 'cd' into a directory

you might do something this

pushd $SysApps/$name
  do stuff 

Don't put ~ inside ""

#!/usr/bin/env bash
set -e
read name

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.