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:
- Run
cat
with no parameters and ctrl+c to interupt. - 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
Measuring Stack Usage for Linux Multi-Threaded App
Replace Text Between Two Lines with Contents of a File Stored in a Variable in Sed
Export_Symbol in Kernel Module | Undefined Symbol During Insmod
Changing the Owner of an Existing Process in Linux
How Can a Program Detect If It Is Running as a Systemd Daemon
Is It Safe to Call Dlclose(Null)
Perf_Event_Open Always Returns -1
How to Get the Output of Ansible Ad-Hoc Command in JSON, CSV or Other Format
Is an Operating System Kernel an Interpeter for All Other Programs
Using Gzip to Compress Files to Transfer with Aws Command
How to Keep Program Running in Background in Ash Shell
How to Get Gcc to Skip Errors, But Still Output Them
How to Ask Bash for the Current Options