Reputation: 1863
I am writing a basic script that has something like this:
LOG_COMMAND=">/tmp/something.log 2>&1"
if [ "${VERBOSE}" == "y" ]; then
LOG_COMMAND="2>&1 | tee /tmp/something.log"
fi
The problem is that when I use the LOG_COMMAND
variable in my script it gets wrapped with single quotes. For example:
set -v
docker build -t test:test . ${LOG_COMMAND}
set +v
I get the following output:
$ /bin/bash testing.sh -v
+ docker build -t test:test . '2>&1' '|' tee /tmp/something.log
"docker build" requires exactly 1 argument.
See 'docker build --help'.
How can I prevent the single quotes from being included?
Upvotes: 0
Views: 77
Reputation: 123470
The simple and robust solution is to put code you want to reuse in a function, rather than in a variable:
log() {
if [ "$VERBOSE" = "y" ]
then
"$@" 2>&1 | tee -a /tmp/something.log
else
"$@" >> /tmp/something.log 2>&1
fi
}
log docker build -t test:test .
The single quotes you see are not being added in any way, they're just bash's notation to show you that the value is a literal string and not part of the command's syntax. "Removing" them wouldn't change the fact that they are just uninterpreted strings any more than whoami() { echo root; }
makes you the super user.
If it helps put things into context, Java has the same "problem" with the same preferred solution:
// Works
System.out.println("hello world".replaceAll("hello", "goodbye"));
// Fails
String replacer = ".replaceAll(\"hello\", \"goodbye\")";
System.out.println("hello world" + replacer);
Upvotes: 3
Reputation: 295403
Variables store data, not code; unless you're going to do something evil, you can't use a variable for this purpose. Instead, just perform the indirection ahead-of-time:
case $VERBOSE in
y) exec 2>&1 > >(tee /tmp/something.log)
*) exec >/tmp/something.log 2>&1
esac
...will redirect stdout and stderr for all code below them. If you only want to make some code subject to that, set up a different pair of conditionally-redirected file descriptors:
case $VERBOSE in
y) exec 3> >(tee /tmp/something.log)
*) exec 3>/tmp/something.log
esac
...and redirect the commands that you want to be subject to those logging rules to that FD:
something_that_should_be_logged >&3 2>&3
Upvotes: 2