1

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?

Mike
  • 2,514
  • 2
  • 23
  • 37
  • 6
    Using `"$@"` already passes spaces exactly as-given. No other escaping need be used. If the code were `$@`, *then* it would have the behavior you describe. – Charles Duffy Oct 01 '14 at 13:49
  • 1
    ...as such, because you aren't providing enough information to reproduce the problem, I don't know that we can help you. – Charles Duffy Oct 01 '14 at 13:51
  • 3
    @mike, an old answer of mine illustrates `$@` vs `"$@"`: http://stackoverflow.com/questions/12314451/accessing-bash-command-line-args-vs/12316565#12316565 – glenn jackman Oct 01 '14 at 13:51
  • although this might help: `--reason="\"This is the reason\""` – isedev Oct 01 '14 at 13:52
  • 2
    @isedev, if that helps, the code is doing something very broken (particularly, an eval pass). It should not be suggested as a solution; instead, whatever code earlier in the file (and not given in the question) is passing the arguments through eval should be fixed. – Charles Duffy Oct 01 '14 at 13:53
  • you're not wrong there :) – isedev Oct 01 '14 at 13:56
  • ...I suppose if we're "lucky", it could not be eval, and instead something like `set -- $*`. Still, though, without seeing the actual code, we're left to speculation, and have an answer that ought to be closed as needing but lacking a SSCCE / MVCE. – Charles Duffy Oct 01 '14 at 14:28
  • I can't see the actual code =[ – Mike Oct 01 '14 at 14:31
  • @Mike, ...why can't you? You saw enough of it to copy a few lines out. – Charles Duffy Oct 01 '14 at 19:13
  • I put in the who .sh file but the java stuff i don't have access to – Mike Oct 02 '14 at 19:29
  • have you tried running the `java ...` command manually replacing `"$@"` with `ack --id=10 --reason="This is the reason I ack"` (you'll need to set the environment as per the script)... does it reproduce the problem or does it work? – isedev Oct 02 '14 at 19:32
  • The shell script is what I was talking about -- if the problem is in the Java, then that's bigger issues, but there could be other parts of the script messing things up (and I already gave examples earlier in this comment thread of how). Anyhow -- run the script with `sh -x yourscript` or `bash -x yourscript`, and it'll show how it's passing things to the JVM, which will make it clear which component is at fault. – Charles Duffy Oct 02 '14 at 20:21
  • Eww. See http://mywiki.wooledge.org/ParsingLs -- using `ls` programatically is pretty much always a bad idea -- and http://mywiki.wooledge.org/BashPitfalls. – Charles Duffy Oct 02 '14 at 21:53
  • ...I've added a cleaned-up copy of the code to my answer. Unfortunately, unless you have some fairly unlikely circumstances (directory names with spaces), it probably won't help -- the likely finding is a bug inside the 3rd-party Java. – Charles Duffy Oct 02 '14 at 22:01

1 Answers1

3

"$@" 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.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Thanks for the clean up, I'll try this out and see what happens though I suspect the problem is in Java. +1 – Mike Oct 03 '14 at 17:44
  • I still suggest using (and perhaps posting the output of, if you have any questions) `sh -x yourscript`. – Charles Duffy Oct 03 '14 at 17:46