user6558378
user6558378

Reputation:

bash set environment variable before command in script

I compile my project with:

debug=yes make -j4 or debug=no make -j4

The debug variable changes some compiler flags in the Makefile

Instead of typing this repeatedly in the shell, I wrote this script (lets call it daemon):

#!/bin/bash

inotifywait -q -m -e close_write `ls *.c* *.h*` |
while read; do
    make -j4
done

so I just do ./daemon which automatically builds whenever a file is written to.

However, I would like to be able to pass the debug=no make -j4 to the ./daemon script like this:

./daemon debug=no make -j4

So I modified the script:

#!/bin/bash

if [ $# -lt 1 ]; then
    echo "Usage `basename $0` [COMMAND]"
    exit 1;
fi
inotifywait -q -m -e close_write `ls *.c* *.h*` |
while read; do
    "$@"
done

This works with ./daemon make -j4 but when I say daemon debug=no make -j4 I get the following error:

./daemon: line 9: debug=no: command not found

How can I make it so debug=no is recognized as a variable and not a command in the daemon script?

Thanks

Upvotes: 1

Views: 3623

Answers (3)

that other guy
that other guy

Reputation: 123470

Variable expansions will only ever become arguments (including the zeroth argument: the command name).

They will never become:

  • Redirections, so you can't var='> file'; cmd $var
  • Shell keywords or operators, so you can't var='&'; mydaemon $var
  • Assignments, including prefix assignments, so you can't var='debug=yes'; $var make as you discovered
  • Command expansions, loops, process substitutions, &&/||, escape sequences, or anything else.

If you want to do this though, you're in luck: there's a standard POSIX tool that will turn leading key=value pairs into environment variables and run the program you want.

It's called env. Here's an example:

run() {
  env "$@"
}

run debug=yes make -j 4

Though TBH I'd use chepner's solution

Upvotes: 1

chepner
chepner

Reputation: 531185

The expansion of "$@" is parsed after any pre-command assignments are recognized. All you need to do is ensure that debug=... is in the environment of the command that runs make, which is your daemon script.

debug=no ./daemon make -j4

Upvotes: 1

Mischa
Mischa

Reputation: 2298

You always need to put the (env) variable settings at the beginning of the command, i.e. before "daemon".

Upvotes: 0

Related Questions