Bash: Creating a shell variable in a bash script that I can access from command line - linux

I have very little experience working with bash. With that being said I need to create a bash script that takes your current directory path and saves it to a shell variable. I then need to be able to type "echo $shellvariable" and have that output the directory that I saved to that variable in the bash script. This is what I have so far.
#!/bin/bash
mypath=$(pwd)
cd $1
echo $mypath
exec bash
now when I go to command line and type "echo $mypath" it outputs nothing.

You can just run source <file_with_your_vars>, this will load your variables in yours script or command line session.
> cat source_vars.sh
my_var="value_of_my_var"
> echo $my_var
> source source_vars.sh
> echo $my_var
value_of_my_var

You have to export the variable for it to exist in the newly-execed shell:
#!/bin/bash
export mypath=$(pwd)
cd $1
echo $mypath
exec bash

Hello
'env -i' gives control what vars a shell/programm get...
#!/bin/bash
mypath=$(pwd)
cd $1
echo $mypath
env -i mypath=${mypath} exec bash
...i.e. with minimal environment.

Related

bash command working from terminal but not from script [duplicate]

a.sh
#! /bin/sh
export x=/usr/local
we can do source ./a in command-line. But I need to do the export through shell script.
b.sh
#! /bin/sh
. ~/a.sh
no error... but $x in command-line will show nothing. So it didn't get export.
Any idea how to make it work?
a.sh
#! /bin/sh
export x=/usr/local
-----------
admin#client: ./a.sh
admin#client: echo $x
admin#client: <insert ....>
You can put export statements in a shell script and then use the 'source' command to execute it in the current process:
source a.sh
You can't do an export through a shell script, because a shell script runs in a child shell process, and only children of the child shell would inherit the export.
The reason for using source is to have the current shell execute the commands
It's very common to place export commands in a file such as .bashrc which a bash will source on startup (or similar files for other shells)
Another idea is that you could create a shell script which generates an export command as it's output:
shell$ cat > script.sh
#!/bin/sh
echo export foo=bar
^D
chmod u+x script.sh
And then have the current shell execute that output
shell$ `./script.sh`
shell$ echo $foo
bar
shell$ /bin/sh
$ echo $foo
bar
(note above that the invocation of the script is surrounded by backticks, to cause the shell to execute the output of the script)
Answering my own question here, using the answers above: if I have more than one related variable to export which use the same value as part of each export, I can do this:
#!/bin/bash
export TEST_EXPORT=$1
export TEST_EXPORT_2=$1_2
export TEST_EXPORT_TWICE=$1_$1
and save as e.g. ~/Desktop/TEST_EXPORTING
and finally $chmod +x ~/Desktop/TEST_EXPORTING
--
After that, running it with source ~/Desktop/TEST_EXPORTING bob
and then checking with export | grep bob should show what you expect.
Exporting a variable into the environment only makes that variable visible to child processes. There is no way for a child to modify the environment of its parent.
Another way you can do it (to steal/expound upon the idea above), is to put the script in ~/bin and make sure ~/bin is in your PATH. Then you can access your variable globally. This is just an example I use to compile my Go source code which needs the GOPATH variable to point to the current directory (assuming you're in the directory you need to compile your source code from):
From ~/bin/GOPATH:
#!/bin/bash
echo declare -x GOPATH=$(pwd)
Then you just do:
#> $(GOPATH)
So you can now use $(GOPATH) from within your other scripts too, such as custom build scripts which can automatically invoke this variable and declare it on the fly thanks to $(pwd).
script1.sh
shell_ppid=$PPID
shell_epoch=$(grep se.exec_start "/proc/${shell_ppid}/sched" | sed 's/[[:space:]]//g' | cut -f2 -d: | cut -f1 -d.)
now_epoch=$(($(date +%s%N)/1000000))
shell_start=$(( (now_epoch - shell_epoch)/1000 ))
env_md5=$(md5sum <<<"${shell_ppid}-${shell_start}"| sed 's/[[:space:]]//g' | cut -f1 -d-)
tmp_dir="/tmp/ToD-env-${env_md5}"
mkdir -p "${tmp_dir}"
ENV_PROPS="${tmp_dir}/.env"
echo "FOO=BAR" > "${ENV_PROPS}"
script2.sh
shell_ppid=$PPID
shell_epoch=$(grep se.exec_start "/proc/${shell_ppid}/sched" | sed 's/[[:space:]]//g' | cut -f2 -d: | cut -f1 -d.)
now_epoch=$(($(date +%s%N)/1000000))
shell_start=$(( (now_epoch - shell_epoch)/1000 ))
env_md5=$(md5sum <<<"${shell_ppid}-${shell_start}"| sed 's/[[:space:]]//g' | cut -f1 -d-)
tmp_dir="/tmp/ToD-env-${env_md5}"
mkdir -p "${tmp_dir}"
ENV_PROPS="${tmp_dir}/.env"
source "${ENV_PROPS}"
echo $FOO
./script1.sh
./script2.sh
BAR
It persists for the scripts run in the same parent shell, and it prevents collisions.

Bash script tee command syntax issue

I want to echo the following line at the end of ~/.profile file using tee command:
export PATH="$HOME/.local/bin:$PATH"
To do this my bash script looks like this
#!/bin/bash
path_env="export PATH="$HOME/.local/bin:$PATH""
echo $path_env| sudo tee -a $HOME/.profile > /dev/null
But whenever I am executing the script it is also executing $PATH and $HOME value and inserts that in ~./profile file which I do not want. I only want the exact line to be passed by the bash script instead of replacing $PATH and $HOME with its own values.
I only want the exact line to be passed by the bash script instead of replacing $PATH and $HOME with its own values.
Och, right, so do not expand it. Quoting.
path_env='export PATH="$HOME/.local/bin:$PATH"'
echo "$path_env" | sudo tee -a "$HOME/.profile" > /dev/null

Sourcing files in shell script vs sourcing on command line

I have the problem that my shell script is not acting exactly the same as my manual typing into a console. I am attempting to find and source some setup files in a shell script as follows:
#!/bin/bash
TURTLE_SHELL=bash
# source setup.sh from same directory as this file
_TURTLE_SETUP_DIR=$(builtin cd "`dirname "${BASH_SOURCE[0]}"`" > /dev/null && pwd)
. "$_TURTLE_SETUP_DIR/turtle_setup.sh"
This bash file calls a .sh file:
#!/bin/env sh
_TURTLE_ROS_SETUP_DIR=$_TURTLE_SETUP_DIR/../devel
if [ -z "$TURTLE_SHELL" ]; then
TURTLE_SHELL=sh
fi
if [ -d "$PX4_FIRMWARE_DIR/integrationtests" ]; then
if [ -f "$PX4_FIRMWARE_DIR/integrationtests/setup_gazebo_ros.bash" ]; then
. "$PX4_FIRMWARE_DIR/integrationtests/setup_gazebo_ros.bash" "$PX4_FIRMWARE_DIR"
fi
fi
if [ "$TURTLE_SHELL" = "bash" ]; then
if [ -f "$_TURTLE_ROS_SETUP_DIR/setup.bash" ]; then
source $_TURTLE_ROS_SETUP_DIR/setup.bash
fi
else
if [ "$TURTLE_SHELL" = "sh" ]; then
if [ -f "$_TURTLE_ROS_SETUP_DIR/setup.sh" ]; then
source $_TURTLE_ROS_SETUP_DIR/setup.sh
fi
fi
fi
The line in question is:
. "$PX4_FIRMWARE_DIR/integrationtests/setup_gazebo_ros.bash" "$PX4_FIRMWARE_DIR"
I have made sure that this code is actually running and that my environment variables are correct. If I run this command on the command line everything works well. However, the same is not true when the file is sourced via shell script. Why is this? Is there something different about the environment of a shell script that is different from a command line. Also, how can I fix this problem?
Edit:
I am sourcing either the .bash or the .sh scale, depending upon which shell I am using.
Edit 2:
I am sourcing this script. Thus, everything is run in my default bash terminal, and it is all run within the same terminal and not a terminal spawned from a child process. Why is the script not sourcing setup_gazebo_ros.bash within the current shell?
It's the same reason why you source the env script and not run it. When you run the script it runs in a new shell and the variables are not transferred back to the parent shell.
To illustrate
$ cat << ! > foo.sh
> export foo='FOO'
> !
$ chmod +x foo.sh
$ ./foo.sh
$ echo $foo
$ source ./foo.sh
$ echo $foo
FOO

Difference between executing a script with 'bash cd.sh' and 'source cd.sh'? [duplicate]

This question already has answers here:
What is the difference between using `sh` and `source`?
(5 answers)
Closed 7 years ago.
Explain the difference between executing a script with bash cd.sh and source cd.sh
cd.sh contains:
#!/bin/sh
cd /tmp
bash execute the script in a child shell that cannot modify the environment of the invoking shell while source executes the script in the current shell:
test.sh
#!/bin/sh
export MY_NAME=chucksmash
echo $MY_NAME
Running test.sh:
chuck#precision:~$ bash test.sh
chucksmash
chuck#precision:~$ echo $MY_NAME
chuck#precision:~$ source test.sh
chucksmash
chuck#precision:~$ echo $MY_NAME
chucksmash
chuck#precision:~$
In bash, commands that look like source script.sh (or . script.sh) run the script in the current shell, regardless of the #! line.
Therefore, if you have a script (named script.sh in this example):
#!/bin/bash
VALUE=1
cd /tmp
This would print nothing (because VALUE is null) and not change your directory (because the commands were executed in another instance of bash):
bash script.sh
echo $VALUE
This would print 1 and change your directory to /tmp:
source script.sh
echo $VALUE
If you instead had this script (named script.py in this example):
#!/usr/bin/env python
print 'Hello, world"
This would give a WEIRD bash error (because it tries to interpret it as a bash script):
source shell.py
This would *also *give a WEIRD bash error (because it tries to interpret it as a bash script):
bash shell.py
This would print Hello, world:
./shell.py # assuming the execute bit it set

Linux bash script: share variable among terminal windows

If I do this:
#!/bin/bash
gnome-terminal --window-with-profile=KGDB -x bash -c 'VAR1=$(tty);
echo $VAR1; bash'
echo $VAR1
How can I get the last line from this script to work? I.e., be able to access the value of $VAR1 (stored on the new terminal window) from the original one? Currently, while the first echo is working, the last one only outputs an empty line.
The short version is that you can't share the variable. There's no shared channel for that.
You can write it to a file/pipe/etc. and then read from it though.
Something like the following should do what you want:
#!/bin/bash
if _file=$(mktemp -q); then
gnome-terminal --window-with-profile=KGDB -x bash -c 'VAR1=$(tty); echo "$VAR1"; declare -p VAR1 > '\'"$_file"\''; bash'
cat "$_file"
. "$_file"
echo "$VAR1"
fi

Resources