Parsing current location from a bash script when sourcing another script - bash

I have a bash script that is saved in a location included in my PATH variable. Within this script I need to source another script that is saved in a different location. In my first (main) script I change directory to the location of this second script and then I source it.
cd $path_of_2nd_script && source 2nd_script
The problem is that in my second script (the one that is sourced) I have some variables that need to retrieve the location of the second script with dirname $0. The problem is that is retrieving the location of the first script ($path_of_1st_script), not the $path_of_2nd_script where I changed directory in my main script, just before sourcing it. How can I pass the path_of_2nd_script into 2nd_script? Does it make sense?

Change source 2nd_script to e.g. bash 2nd_script. When using source, the argument will be executed in the current shell environment, which means that $0 will refer to the first script.

It is not clear why you are sourcing your second script rather than executing as a child process, in which case $0 would resolve to the name of the second script itself.
If you could change the second script to grab its directory from its $1 and then change the first script this way:
cd "$path_of_2nd_script" && source 2nd_script "$path_of_2nd_script"

Related

Running a bash script stored in a variable

I want to send the path to a bash script which sources some environmental variables as an argument to another bash script to run it and use the environmental variables. It works well with no arguments if I hard coded the path to the bash script to run it works and I can retrieve the environmental variables in the main script. the problem happens when I send the path as an argument it does not want to run it.
for example if the path is /path/script.bash and I send the path as an argument I get the error that /path/env_set: No such a file or directory
I run the script by this line
. $1 (this doesn't work)
. /path/script.bash (this works)
if I use
bash -c $1
the bash file runs but it does not set the environmental variables to use it in the main script
I don't know why env_set replaces the script name when I use arguments. Is there any approach to achieve this or any work around to achieve my goal?
It sounds like the problem could be either with your quoting, or with relative paths.
Quoting isn't just about spaces, it's also about pathname expansion (ie. []?* characters).
Do
. "$1"
(not . $1)
And remember, if you're giving a relative path for the environment script (or that script uses some relative paths), you will have a problem. Those paths are relative to the pwd - which is wherever you happen to be when you execute the main script (not where any of the script files themselves happen to be located, for example).
Finally, you can debug this problem by throwing echo at the start, and running the script (if it's safe to do that):
echo . "$1"
exit # Add exit here if you don't want to run w/o the vars.
Now you can see what you're actually trying to source.
In script 1, in your main code, you can call and run script 2,
. ./script 2
The first . stands for current shell, and the second . for current directory.
which will create the environment variables for you, and configure any other settings as well in the same terminal.
Afterwards when script 2 has finished running, script 1 would continue to run, and your environment variables which was created in script 2, will be accessible for script 1 to use in the same session.

How to change current directory via shell script and execute command there?

I have this script:
#!/bin/bash
cd ~/my-dir && bash && runall
And I added this script to my $PATH and when I run this script it does 2 things first.
It changes the current directory and execute bash so that my shell also changes the current dir and i can work there.
Run runall (another shell script) in this folder.
Actual Result:
Script changes my current shell directory successfully.
However, runall is not executed.
Expected Result:
Script changes current shell directory of mine to the my-dir and then execute runall
How can I solve this?
Note:
I know that i can do this:
cd some-dir/ && runall
But this will not change my current session to that dir. I also want to change my current shell directory.
Reason:
I want to also change my current working directory so that i can run other manual commands there after runall executed.
This is very nearly a duplicate of Change the current directory from a Bash script, and the answer is very similar -- the only difference being the appending of the command you want to run.
Don't use a script at all; instead, in your ~/.bashrc or similar, define a function:
runInMyDir() {
cd ~/my-dir || return
runall
}
...to define a command runInMyDir. (If you want runall to happen in the background, add a & at the end of that line).
If you do want a script, that script needs to be sourced rather than executed out-of-process -- when a program is executed as an executable external to the shell, it has already been split off from the original shell before it starts, so it has no opportunity to change that shell's behavior. Thus, if you created a file named runInMyDir with the commands cd ~/my-dir || return and runall, you would need to run source runInMyDir rather than just runInMyDir to invoke it.

Setting variable in a file does not work

I have a file run_me
#!/bin/bash
export BOBO=MOMO
After I run run_me, the variable BOBO isn't set. Why? How can it be fixed?
You need to source it:
. ./run_me
OR
source ./run_me
In order to run this script in current shell otherwise BASH creates a new sub-shell and executes the script in that sub-shell therefore all the changes (variable etc) are not reflected in the current parent shell.

How do I set an alias from a shell script?

I'm trying to set an alias that applies to the current shell (the shell I'm running the script from) from a shell script. The alias is for cd-ing into the folder of the script. Here's the (not working) script:
#!/bin/bash
shopt -s expand_aliases
DIR=$(cd $(dirname "$0"); pwd) # Detect the folder of the script.
alias cdr="cd $DIR" # cd into the folder.
I quickly realized that this didn't work because the alias it made was pertinent to the script's subshell.
Then, I tried to source the file (as in . makeAlias.sh). However, this produced an error: dirname: illegal option -- b.
How do I write a bash script that makes an alias relevant to the outer shell (the shell running the script)?
The immediate problem is that the value of $0 is now -bash. You might want to refactor your code to use a different reference point, or simply hard-code the path.
To answer the "how do I ...?" you aren't doing anything wrong, it's just that the logic has to be adapted to a different environment -- specifically, when you source a script, $0 is that of the parent process, not the name of the script you are sourcing.
Depending on what you are trying to accomplish, maybe this alternative design could work?
newr () { r=$(pwd); }
cdr () { cd "$r"; }
newr
That is, cdr simply changes directory to whatever the variable r contains. The function newr can be used to conveniently set r to your current working directory. You'd define these in your .bashrc or similar, and use them interactively
./makeAlias.sh will be executed in a sub-shell and the changes made apply only the to sub-shell. Once the command terminates, the sub-shell goes and so do the changes.
Sourcing the file using . ./makeAlias.sh or source ./makeAlias.sh will read and execute commands from the file-name argument in the current shell context, that is when a script is run using source it runs within the existing shell, any variables created or modified by the script will remain available after the script completes.

How to run 'cd' in shell script and stay there after script finishes?

I used 'change directory' in my shell script (bash)
#!/bin/bash
alias mycd='cd some_place'
mycd
pwd
pwd prints some_place correctly, but after the script finished my current working directory doesn't change.
Is it possible to change my path by script?
You need to source the file as:
. myfile.sh
or
source myfile.sh
Without sourcing the changes will happen in the sub-shell and not in the parent shell which is invoking the script. But when you source a file the lines in the file are executed as if they were typed at the command line.
While sourcing the script you want to run is one solution, you should be aware that this script then can directly modify the environment of your current shell. Also it is not possible to pass arguments anymore.
Another way to do, is to implement your script as a function in bash.
function cdbm() {
cd whereever_you_want_to_go
echo arguments to the functions were $1, $2, ...
}
This technique is used by autojump:
http://github.com/joelthelion/autojump/wiki
to provide you with learning shell directory bookmarks.
The script is run in a separate subshell. That subshell changes directory, not the shell you run it in. A possible solution is to source the script instead of running it:
# Bash
source yourscript.sh
# or POSIX sh
. yourscript.sh
It can be achieved by sourcing. Sourcing is basically execute the script in the same shell whereas normal execution(sh test.sh or ./test.sh) will create sub shell and execute script there.
test.sh
cd development/
ls
# Do whatever you want.
Execute test.sh by
source test.sh
. is shortest notation for source. So you can also do by
. test.sh
This will execute the script and change the directory of current shell to development/.
whenever you run a script on your login shell, a new subprocess is spawned and the script execution is done in a subshell.Once the script completes, the subshell exits and you are returned to the login shell.Hence whenever you do a cd through a script,the directory is changed to the path specified by cd, but by the time script finishes you come back to your login shell to the working directory from where you started the script.
The way to overcome this is use,
source yourscript.sh
what source does is it executes the script as TCL script, i.e it has the same effect as when you typed each line on the command line of your login shell and it executed from there. So this way when the script finishes after cd , it stays in that directory.
Another practical solution is to end your script by opening another shell session.
For instance:
#!/bin/bash
cd some_place
bash
This is useful, in my case, for scripts located in my ~/bin for instance, called from any other place. It is just a bit painful to type source ~/bin/mygoodoldscript instead of mygoo<TAB><ENTER>.
The downside is that the additional shell takes up a few more resources (not much).
Though there are answers. I think the intention of question is to use script to navigate to specific path.
Here is a simple practical solution works here without cancel out existing terminal environment flag.
provide a bash/tch/sh script to work for path generation
/* .goto.sh */
#!/usr/bin/env bash
echo '~/workspace'
add alias to the script output
alias goto 'cd `.goto.sh`'

Resources