Bash -C Variable Does Not Get Assigned

bash -c variable does not get assigned

Double quotes expand variables, so your command is expanded to

bash -c "var='test' && echo"

if $var is empty when you run it. You can verify the behaviour with

var=hey
bash -c "var='test' && echo $var"

Switch the quotes:

bash -c 'var="test" && echo $var'

Assign value of C variable to bash variable

You may use the setenv to set an environment variable which is accessible by your script.

#include <stdlib.h>

int main(int argc, char **argv) {
setenv("VAR", argv[1], 1);
system("echo $VAR");
return 0;
}

bash -c does not set $? as expected

The expansions of $? and $status in your first example are done by your current shell - that is before the bash you're running ever sees the command string. Use single quotes:

$ bash -c 'ls BLAH; echo $?; export status=$?; echo $status'
ls: BLAH: No such file or directory
1
0

or otherwise:

$ bash -c "ls BLAH; echo \$?; export status=\$?; echo \$status"
ls: BLAH: No such file or directory
1
0

How do I define variable inside bash -c?

The trouble is not caused by the script you pass to bash -c but by the current instance of the shell (bash or whatever it is).

The script is an argument in a command line. Because it is enclosed in double quotes, the shell does variable expansion in it. It replaces ${FOOBARLIST[@]} with the value of the FOOBARLIST array defined in the current environment.

But there isn't any FOOBARLIST variable in the current environment, ${FOOBARLIST[@]} is replaced by an empty strings and the command it runs is:

bash -c "FOOBARLIST=(foo bar) ; echo "

The simplest solution is to enclose the script into single quotes (apostrophes). This way the current shell doesn't replace anything in it and passes it as is to bash -c:

bash -c 'FOOBARLIST=(foo bar); echo ${FOOBARLIST[@]}'

Failed to assign value to a variable in bash -c commands;

Simply: Use single quotes.

bash -c 'variable=1111; echo $variable'

The quotes are meaningful to the shell. Double quotes escape spaces and globs (roughly speaking, * expansion). but still allow for string interpolation. Single quotes do the same as double quotes, but they also escape the $.

Confused with `bash -c` command - does not work with global variables

Your double quoted string is being expanded BEFORE the commands in the string are being interpreted by bash -c so that $? is likely a previous command's exit code.

You can see this with an example where we also use the -x flag to see what's happening under the hood:

$ set -x
$ bash -c "v=5; echo $v"
+ bash -c 'v=3; echo '

You can see that there is no value of $v to echo when execution hits that line as $v was already replaced before the command was interpreted by bash -c.

For further expirementation; to get nearly the same output as your issue, do the following:

  1. Run cat with no parameters and ctrl+c to interupt.
  2. Run bash -c "echo 'hi'; echo $?"

You should get hi and 130 as the output, which was the exit code of your sigint'd cat command. (note that it's not the exit 0 of the echo "hi" as you might expect).


Thankfully for your command, you can just swap out your quotes to avoid this issue:

/bin/bash -c '(while true; do \
sleep 1; \
ping -c 1 "www.google.com"; \
if [ $? -eq 0 ]; then break; fi; \
done); \
exit 0'

bash wont assign variables

You need while loop to read the file line by line:

usercount=0
while read l; do
let usercount=$usercount+1;
done < userfile

Though just to count line you can very well do:

usercount=$(wc -l < userfile)

Setting variable in bash -c

You have to escape the $ sign in the final echo command, or the variable $HOST_IPS will be substituted into the command string before the subshell is spawned:

/usr/bin/bash -c "HOST_IPS=$(/usr/bin/ifconfig | /usr/bin/awk 'BEGIN {cnt=0} {if($0 ~ /inet / && cnt==1) {print $2} cnt++}'); echo \$HOST_IPS"

For more immediate visibility:

#                                                  v-- insert backslash here
/usr/bin/bash -c "HOST_IPS=$(same as before); echo \$HOST_IPS"

Contrary to @gniourf_gniourf's comment, it is not actually necessary to escape the other dollar signs. However, as written, the command substitution is not performed by the subshell (!); its result is substituted into the command string that is passed to the subshell. The calls

mypid() { echo $$; }
bash -c "pid=$(mypid); echo \$pid; mypid"

demonstrate the way it works: it will once print the PID of the parent shell and once complain that mypid is not a known command because the subshell does not know the function.

Since running the ifconfig | awk command in the parent shell is unlikely to be a problem, you can probably leave the command substitution part unchanged. If it is important that the command be run by the subshell, you'll have to escape all the things there as well.



Related Topics



Leave a reply



Submit