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.

6
  • why do you even wrap the cd with chdir? Commented Oct 1, 2015 at 18:56
  • good question, because I'm going to use it afterwards. Commented Oct 1, 2015 at 19:03
  • Are you asking why your current directory isn't changed after the script is done running? Commented Oct 1, 2015 at 19:14
  • 4
    Related: unix.stackexchange.com/questions/38808/why-is-cd-not-a-program Commented Oct 1, 2015 at 19:23
  • 1
    Is there a way to actually change it, I searched a lot online, fund that define a function is a way, that's why I defined a change dir function. But it doesn't work for my case. Commented Oct 1, 2015 at 19:31

2 Answers 2

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
5
  • 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. Commented Oct 1, 2015 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. Commented Oct 1, 2015 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. Commented Oct 1, 2015 at 22:34
  • 1
    @rubynorails Double check your test case, there is no such bug with cygwin I'm aware of. Commented Oct 1, 2015 at 23:00
  • 1
    I stand corrected. source works just fine. A tip of the hat to you. Commented Oct 1, 2015 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.

7
  • It's not exactly a subshell, just a different process. Commented Oct 1, 2015 at 19:36
  • @PSkocik Thank you, I've updated the answer to try and reflect this. Commented Oct 1, 2015 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. Commented Oct 1, 2015 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. Commented Oct 1, 2015 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. Commented Oct 1, 2015 at 21:09

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.