Setting variables with spaces within .env - bash

I have a .env file with a bunch of variables and I just came across an error.
One of the variables has spaces.
TEST="hello world"
So when I run this, learned about in this answer here.
env $(<.env)
I get this error.
env: world"': No such file or directory
How do I set variables with spaces within .env?

If your command is just a shell command, you could run your command in a subshell like this:
( . .env ; echo "$TEST" )
The source or . builtin has no problem with assignments containing spaces. It will set the variables in the .env file in the current shell's environment.
In the more likely case of calling an external program, you'll also have to add 'export' to each assignment in your env file like this:
export TEST="hello world"
This is necessary because source does not export assigned variables as env does, i.e. they are set inside the subshell only but not in the environment of another process started inside that subshell.

juste put the word that contains the space between " ".

Related

Define a variable in the .environment file and use (refrence) that in the .sh file

I have written a bash script to create a folder if it doesn't already exist and have set the variables in my environment file and referenced that in my .sh file
Below is my script I have added the variables in the .sh file which I have added in my environment file.
#!/bin/bash
if [ ! -d "$checkfolder" ]; then
mkdir -p "$createfolder";
fi
I have set the following environment variables in my /etc/environment file
checkfolder=/home/ubuntu/hello23
createfolder=/home/ubuntu/hello23
when I execute the script I am getting the following errors:
ubuntu#:~/cicd$ ./createfolder.sh
mkdir: cannot create directory ‘’: No such file or directory
Here is the normal script I have written, which works and creates a folder if it does not exist
if [ ! -d /home/ubuntu/hello ]; then
mkdir -p /home/ubuntu/hello;
fi
What is the issue here and what changes should i make?
/etc/environment and ~/.pam_environment are read when you log in. If you've just edited those files, your changes don't apply to the current session.
If you want to apply the changes to your current session, you can run
. /etc/environment
to set the variables in your current shell. This only works if the values of the variables don't contain any shell speciavairablel characters (spaces, ()[]{}\|&;<>~*?'"`$# and I may be forgetting a few), because the syntax of /etc/environment is only an approximation of the syntax of the shell.
If you've added new variables, and not just changed their value, you'll also need to export them (VAR=value in the shell only creates a shell variable, not an environment variable).
export MY_HOME checkfolder createfolder
or more generally
export $(sed -n 's/^\([A-Za-z0-9_]*\)=.*/\1/p')
There is no file that sets the environment for every new program, because that would defeat the point of the environment, which is that every process has its own which it inherits from its parents. If there was a “global environment file”, it would make it impossible to run programs with a different environment. If you want a global configuration, read a configuration file:
if [ -e ~/.my_application_configuration.sh ]; then
. ~/.my_application_configuration.sh
fi
There is a way to have a file that sets the environment for every bash script (only bash scripts, not sh scripts): put the full path to the file in the environment variable BASH_ENV. As I explained just above, this is usually a bad idea.

Load environment variables from file just for the next script

I have one of those .env files with several variables set, like:
VAR1=111
VAR2=222
I want to run a script (without changing it) that makes use of those variables.
I know I can source that file in the shell and export the variables from the file, like:
set -a
source myenvs.env # this is my .env file
set +a
./myscript.sh # this will use the variables
The problem with that is it loads all those variables in my shell, which I don't want (shell pollution.)
What I'm looking for is the equivalent of using env VAR1=111 VAR2=222 ./myscript.sh but getting those variables from the .env file instead.
Do that in a subshell and main shell's environment won't be altered. E.g:
(
set -a
source myenvs.env # this is my .env file
exec ./myscript.sh # avoid unnecessary fork()
)
The truth is I need to keep that script flexible to run with different combinations of settings. Imagine I have several .env files like development.env, stagin.env, repro-bug-123.env, etc.
A function would be more useful in that case.
with_env() (
set -a
source "$1"
shift
exec "$#"
)
with_env myenvs.env ./myscript.sh
Declare vars that you don't want to change as read only
declare -r VAR3 VAR4
and source the rest
. ./myenvs.env

unable to fetch environment varible in shell script

I want to fetch some environment variable which are set in .bash_aliases file. I want use them in my bash script
#!/bin/dash
echo $PATH
echo $DEPOT_TOOLS
Both are coming empty string once call it in myscript. In the terminal these variable are printing successfully.
All you have to do is source the .bash_aliases file -- however as dash does only supports POSIX shell syntax you'll likely find that there are definitions inside of .bash_aliases that don't work for dash. If this is the case simply put your aliases inside of a different file and source that. Also the environment variable PATH is generally always available not sure what's going on with your system.
#!/bin/dash
. .some_aliases
echo "$PATH"
echo "$something_else"

*export* all variables from key=value file to shell

If I want to inherit environment variables to child processes, i do something like:
export MYVAR=tork
Assume I have a a file site.conf containing assignments of values (that can contain spaces) to variables:
EMAIL="dev#example.com"
FULLNAME="Master Yedi"
FOO=bar
Now I would like to process this file whenever I open a new shell (e.g. with some code in ~/.bashrc or ~/.profile), so that any processes started from within that newly opened shell will inherit the assignments via environmental variables.
The obvious solution would be to prefix each line in site.conf with an export and just source the file. However I cannot do this since the file is also read (directly) by some other applications, so the format is fixed.
I tried something like
cat site.conf | while read assignment
do
export "${assignment}"
done
But this doesn't work, for various reasons (the most important being that export is executed in a subshell, so the variable will never be exported to the children of the calling shell).
Is there a way to programmatically export unknown variables in bash?
Run set -a before sourcing the file. This marks all new and modified variables that follow for export automatically.
set -a
source site.conf
set +a # Require export again, if desired.
The problem you observed is that the pipe executes the export in a subshell. You can avoid that simply by using input redirection instead of a pipe.
while read assignment; do
export "$assignment"
done < site.conf
This won't work, however, if (unlikely though it is) you have multiple assignments on one line, such as
EMAIL="dev#example.com" FULLNAME="Master Yedi"

Global environment variables in a shell script

How to set a global environment variable in a bash script?
If I do stuff like
#!/bin/bash
FOO=bar
...or
#!/bin/bash
export FOO=bar
...the vars seem to stay in the local context, whereas I'd like to keep using them after the script has finished executing.
Run your script with .
. myscript.sh
This will run the script in the current shell environment.
export governs which variables will be available to new processes, so if you say
FOO=1
export BAR=2
./runScript.sh
then $BAR will be available in the environment of runScript.sh, but $FOO will not.
When you run a shell script, it's done in a sub-shell so it cannot affect the parent shell's environment. You want to source the script by doing:
. ./setfoo.sh
This executes it in the context of the current shell, not as a sub shell.
From the bash man page:
. filename [arguments]
source filename [arguments]
Read and execute commands from filename in the current shell
environment and return the exit status of the last command executed
from filename.
If filename does not contain a slash, file names in PATH are used to
find the directory containing filename.
The file searched for in PATH need not be executable. When bash is not
in POSIX mode, the current directory is searched if no file is found
in PATH.
If the sourcepath option to the shopt builtin command is turned off,
the PATH is not searched.
If any arguments are supplied, they become the positional parameters
when filename is executed.
Otherwise the positional parameters are unchanged. The return status
is the status of the last command exited within the script (0 if no
commands are executed), and false if filename is not found or cannot
be read.
source myscript.sh is also feasible.
Description for linux command source:
source is a Unix command that evaluates the file following the command,
as a list of commands, executed in the current context
#!/bin/bash
export FOO=bar
or
#!/bin/bash
FOO=bar
export FOO
man export:
The shell shall give the export attribute to the variables corresponding to the specified names, which shall cause them to be in the environment of subsequently executed commands. If the name of a variable is followed by = word, then the value of that variable shall be set to word.
A common design is to have your script output a result, and require the cooperation of the caller. Then you can say, for example,
eval "$(yourscript)"
or perhaps less dangerously
cd "$(yourscript)"
This extends to tools in other languages besides shell script.
In your shell script, write the variables to another file like below and source these files in your ~/.bashrc or ~/.zshrc
echo "export FOO=bar" >> environment.sh
In your ~/.bashrc or ~/.zshrc, source it like below:
source Path-to-file/environment.sh
You can then access it globally.
FOO=bar
export FOO

Resources