I have an inclusion file test.inc:
export XXX=xxx
I use it when call bash to interpret a string:
bash -c ". test.inc; echo $XXX"
But the variable is not set at the point of echo command. If I do 'export' I can see it though:
bash -c ". test.inc; export"
Shows
declare -x XXX="XXX"
How do I make my first command see the exported variables from sourced files when I use bash -c syntax?
You are using double quotes. Therefore your current shell expands $XXX long before the bash -c instance sees it. Switch to single quotes, or escape the dollar sign.
Related
I have a bash variable which is stored as
var="\"abc\""
So, when i locally print this variable it gives me proper output(with double quotes)
echo "$var"
"abc"
What, I want to do is print it using 'bash -c' option.. but when I do the same, it prints only value without double quotes.
bash -c "echo \"$var\""
abc
bash -c "echo $var"
abc
Can anyone help me on how to preserve the double quotes in my string, when I use it in 'bash -c'. And what does -c actually mean?
In the statement
bash -c "echo $var"
the following happens:
(1) var is expanded (resulting into "abc" including the quotes).
(2) A bash child process is invoked, receiving as first parameter -c and as second paramter echo "abc"
(3) This child process runs the command, i.e. echo "abc", and according to the rules about quote removal, this is equivalent to echo abc, and you don't see any quotes in the output.
You may be tempted to do a
bash -c 'echo "$var"'
instead. In this case, the following happens:
(1) A bash child process is invoked, receiving as first parameter -c and as second paramter echo "$var". Note that $var is not expanded yet, because it is between single quotes.
(2) This child process runs the command, i.e. echo "$var". However, since we are in a child process, the variable var does not exist, and the command is equivalent to echo "", i.e. only a newline is printed.
You can however combine both solution by doing a
export var
bash -c 'echo "$var"'
In this case, var is made available to the child processes of your script, and you will see the quotes being printed.
From info bash
-c If the -c option is present, then commands are read from the first non-option argument command_string.
If there are arguments after the command_string, the first argument is assigned to $0
and any remaining arguments are assigned to the positional parameters.
So the -c option executes the commands within the quotes.
To preserve your double quotes while calling via bash -c, you would need to quote the variable seperately.
$ bash -c "echo '"$var"'"
"abc"
I am using a shell script named script.sh that looks like that :
#!/bin/bash
STRING=$(cat my_string.txt)
${1}
In my_string.txt, there is only :
this_is_my_string
When I execute the commands :
$ STRING="not_my_string"
$ ./script.sh "echo $STRING"
The shell prints not_my_string instead of this_is_my_string and I don’t understand why.
Could you explain me ? And is there any way to force to print the value of the STRING variable which is defined inside the script ?
The variable $STRING is being expanded before the script is called, which is why not_my_string is being assigned.
To delay expansion until after the script is called you should replace "echo $STRING" with 'echo $STRING'. The single quotes cause the expansion to be delayed.
There is some discussion of delayed expansion here:
How to delay expansion of variable in bash if command should be executed on an other machine?
You will also need to replace ${1} in your script with eval ${1}, which will force the string to be executed and expanded.
$ STRING="not_my_string"
$ ./script.sh "echo $STRING"
During command execution bash will expand all variables to the values and actually the following command will be executed:
./script.sh "echo not_my_string"
You can use the following:
./script.sh 'echo $STRING' to send string as is and eval "${1} inside the script to execute argument
This question already has answers here:
Difference between single and double quotes in Bash
(7 answers)
Closed 2 years ago.
I'm trying to execute a list of commands through the command:
bash -l -c "commands"
However, when I define a variable an then try to use them, the variable is undefined (empty). To be clear:
bash -l -c "var=MyVariable; echo $var"
Bash expansion (as explained here) will expand the variable value inside the double quotes before actually executing the commands. To avoid so you can follow either of these options:
Option 1:
Avoid the expansion using single quotes
bash -l -c 'var=MyVariable; echo $var'
Option 2:
Avoid the expansion inside the double quotes by escaping the desired variables
bash -l -c "var=MyVariable; echo \$var"
The second option allows you to expand some variables and some others not. For example:
expandVar=MyVariable1
bash -l -c "var=MyVariable; echo $expandVar; echo \$var"
Bash expands variables inside double quotes. So in effect in your command $var is replaced by the current value of var before the command is executed. What you want can be accomplished by using single quotes:
bash -l -c 'var=MyVariable; echo $var'
Please note that it is rather unusual to invoke Bash as a login shell (-l) when passing a command string with -c, but then you may have your reasons.
i am trying to do this from a Windows command prompt.
C:\cygwin64\bin\bash --login -c "$var="<hallo>" &&
echo "$var""
and i get error :
The system cannot find the file specified.
but this works:
C:\cygwin64\bin\bash --login -c
"var="hello" && echo "$hello""
The login shell seems to cause the problem when it gets a '<'. how can i still assign the string with angle brackets to the shell variable?
When you write
C:\cygwin64\bin\bash --login -c "$var="<hallo>" && echo "$var""
You are expecting the shell to strip off the outer quotes from that argument to -c and end up with a string that looks like
$var="<hallo>" && echo "$var"
but that's not what the shell does.
The shell just matches quotes as it goes along. So the shell sees.
["$var="][<hallo>][" && echo "][$var][""].
You need to escape the inner quotes from the current shell or use different quotes to avoid this parsing problem.
C:\cygwin64\bin\bash --login -c 'var="<hallo>" && echo "$var"'
Note also that I removed the $ from the start of the variable name in the assignment and that I used single quotes on the outside so that the current shell didn't expand $var.
With double quotes on the outside you'd need to use something like this instead.
C:\cygwin64\bin\bash --login -c "var='<hallo>' && echo \"\$var\""
For a similar discussion of shell parsing and how things nest (or don't) with backticks you can see my answer here.
I have a simple shell script to run several commands at once. I can't figure out how to do this:
'mkdir -p $FULL_BACKUP_PATH; cp -r $FULL_PATH/* $FULL_BACKUP_PATH/.;'
If I use single quotes, the variables don't get the values, if I use double quotes, the wildcard does not expand.
Please help
Thanks
I think you want this:
mkdir -p "${FULL_BACKUP_PATH}"; cp -r "${FULL_PATH}/*" "${FULL_BACKUP_PATH}"
Variables inside double quotes get expanded, variables inside single quotes do not. Always put variables inside double quotes if they are paths/directories in case they have spaces in them so the double quotes "hold them together".
If the code appears in shell script that starts with a shebang like this:
#!/bin/bash
you can temporarily add -xv after bash to see the script expanded as it is executed and that will help you debug it, like this:
#!/bin/bash -xv