2

I wrote a script for the purpose of changing directory and then scan a file.

#!/bin/bash
model_dir=/mypath

function chdir () {
  cd $1
}
chdir ${model_dir}/config
if [[ ! -s *.cfg ]]
then
  echo `date` "configure file does not exist"
  exit 1
fi

I don't why my current directory is not changed after I execute this script with source myscript.sh.

huayong.zhou
  • 31
  • 1
  • 3

2 Answers2

3

Your script and specially its inner cd commands works just fine when called from bash with using either the source or the equivalent . commands.

The main issue is, as already stated in @adonis comment, your shell, after properly changing its directory, will exit unless a file precisely named "*.cfg" does exist, which is very doubtful.

As I guess you want to use *.cfg as a pattern, here is how I would slightly modify your script for it to work as expected:

#!/bin/bash # Note that the shebang is useless for a sourced script

model_dir=/mypath

chdir() { # use either function or (), both is a non portable syntax
  cd $1
}

chdir ${model_dir}/config
if [ ! -s *.cfg ]; then # Single brackets here for the shell to expand *.cfg
  echo $(date) "configure file does not exist"
  exit 1  # dubious in a sourced script, it will end the main and only shell interpreter
fi
jlliagre
  • 61,204
  • It did not work for me when using source command, which is why I advised using the . command, but then again I was in a Cygwin environment at the time, so I can't speak for other operating systems. – rubynorails Oct 01 '15 at 22:09
  • 1
    @rubynorails Thesource builtin is strictly equivalent to . under bash, whether you are running bash under cygwin or whatever doesn't make a difference. – jlliagre Oct 01 '15 at 22:17
  • That being said, source did not work for me. . did. Go figure. I use source all the time in my Cygwin dotfiles, but in this particular instance, I had to use . to get the script to function as intended. – rubynorails Oct 01 '15 at 22:34
  • 1
    @rubynorails Double check your test case, there is no such bug with cygwin I'm aware of. – jlliagre Oct 01 '15 at 23:00
  • 1
    I stand corrected. source works just fine. A tip of the hat to you. – rubynorails Oct 01 '15 at 23:22
2

It's because the cd command is executed inside the script and not in your current shell environment. If you want the script to run in your current shell environment, run it like so:

. /path/to/script.sh

Output from my own working example of your script with a pwd in place of your if statement:

Jamey@CNU326BXDX ~
$ /usr/local/bin/this.sh
/cygdrive/c/users/jamey/downloads

Jamey@CNU326BXDX ~
$ . /usr/local/bin/this.sh
/cygdrive/c/users/jamey/downloads

Jamey@CNU326BXDX /cygdrive/c/users/jamey/downloads
$

Notice the current working directory after the script is run the second time.

rubynorails
  • 2,293
  • It's not exactly a subshell, just a different process. – Petr Skocik Oct 01 '15 at 19:36
  • @PSkocik Thank you, I've updated the answer to try and reflect this. – rubynorails Oct 01 '15 at 19:42
  • @PSkocik However, it seems to me that if you are invoking /bin/bash from a current Bash process (such as launching a script), that would be considered a subshell. So the cd would be a process, but it would be launched within the Bash subshell of the script itself, not the parent shell of your current terminal environment. See this. – rubynorails Oct 01 '15 at 19:51
  • 3
    It's a subshell if the parent shell forks without execcing. A subshell has (copy-on-write) access to all the variables of the parent shell. A shell created by forking + execcing bash starts afresh in regards to its (nonexported) variables and the process of starting it will take somewhat longer. – Petr Skocik Oct 01 '15 at 21:00
  • 2
    I disagree with the definition it the link. They mention that $BASH_SUBSHELL indicates the subshel level, which is correct, however if you do bash -c "echo $BASH_SUBSHELL" it'll be 0 not 1, because launching a script does not create a subshell -- it starts a new shell process from scratch. – Petr Skocik Oct 01 '15 at 21:09
  • @rubynorails The cd is not a process, and can not be. It could not change the current directory of the shell, only it's own. It is a "shell builtin". – Volker Siegel Sep 02 '16 at 18:31
  • ^process^command to make everyone happy. – rubynorails Sep 13 '16 at 14:21