Mike
Mike

Reputation: 2614

How to escape spaces in $@

I'm running a command on my client which sends information to my server:

bin/script.sh ack --id=10 --reason="This is the reason I ack"

This sends a message to a server but for the reason field, it fills in:

reason = "This

I've tried to escape the space (and the quote):

--reason=\"This\ is..."

But I still can't escape the space. The above gets recorded :

reason = "This

Inside of script.sh there is a line:

#!/bin/sh

RUNDIR=`dirname $0`/..
HQAPILOGDIR=$RUNDIR/logs

CLASSPATH=$CLASSPATH:$RUNDIR/conf

for h in `ls $RUNDIR/*.jar`; do
   CLASSPATH=$CLASSPATH:$h
done

for i in `ls $RUNDIR/lib/*.jar`; do
   CLASSPATH=$CLASSPATH:$i
done

java -Dhqapi.logDir=$HQAPILOGDIR -cp $CLASSPATH org.hyperic.hq.hqapi1.tools.Shell "$@"

From what I understand, the $@ symbol brings in the arguments from the command line so I'm guessing that this is where my problem is. Is there a way to escape the spaces in my command line arguments? Is the $@ where my problem is occurring?

Upvotes: 1

Views: 325

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295443

"$@" does keep arguments together, without putting them through string-splitting.

You can trivially test this yourself:

#!/bin/sh
printf '%s\n' "$@"

Each argument will be printed on its own line, even if that argument contains spaces.


By the way -- don't escape the quotes! If you write \"This, then the quote is treated as data, which makes it no longer syntax, which means it no longer functions as a quote at all.


Here's a fully cleaned-up copy of your script:

#!/bin/sh

# these aren't environment variables and should be lower-case
rundir=$(dirname "$0")/..
hqapilogdir=$rundir/logs

for h in "$rundir/conf" "$rundir/"*.jar "$rundir/lib/"*.jar; do
   [ -e "$h" ] && CLASSPATH=$CLASSPATH:$h
done

# trim any leading colon from the generated CLASSPATH
CLASSPATH=${CLASSPATH#:}

exec java \
  -Dhqapi.logDir="$hqapilogdir" \
  -cp "$CLASSPATH" \
  org.hyperic.hq.hqapi1.tools.Shell "$@"

If arguments are still parsed incorrectly, the problem is inside the Java code being invoked, not the shell wrapping it. You can verify this by running your script with sh -x scriptname ack --id=10 --reason="This is the reason I ack", and watching the commands invoked below.

Upvotes: 3

Related Questions