0

I am using shell script to call a java program. When calling passing java program I am passing -Dargument which has a path to a directory. This -D argument is read from a file. Now I am facing a issue when this path contains spaces. I tried with quote and also with escaping quotes but both dint work.

Here is my shell script code, test.sh

   D_ARG=`(tr '\r\n' ' ' < argument.dat)
  \#executing java code by passing above argument
   java ${D_ARG} TestProgram

Below is my argument file, argument.dat

  -Dargument1="/Path /To A/File"

When I set the echo on using set -x, I see the shell converting it to

  '-Dargument1="/Path' '/To' 'A/File"'

Where it adds single quotes when it encounters spaces and I get "/To" class not found exception. How to resolve this issue. Any suggestion or help will be really appreciable.

3 Answers 3

2

Try this:

ARGS=

# Do nothing if there are no spaces; if there are spaces, surround with quotes
for arg in $(perl -pe '/ / or next; s/^/"/; s/$/"/' argument.dat); do
    ARGS="$ARGS $arg";
done

java $ARGS TestProgram

This basically has the effect that each time a line has a space in it, it will surround with quotes, so -Da=b c will be turned into "-Da=b c".

Note that "-Da=b c" is strictly equivalent to -Da="b c", or even more bizarre-looking forms of it:

  • '-Da='b\ c;
  • -D"a=b "c;
  • etc etc

The only thing which matters is that whatever characters are input field separators are escaped. Yes, this is legal:

alias l"l=ls"\ -l
Sign up to request clarification or add additional context in comments.

3 Comments

But if I have more than one argument defined in the argument.dat file, then both the arguments are considered as single string, since you have specified quotes for argument "${D_ARG}"
You didn't tell that in the original question ;) In this case, your tr command is not the way to handle that.
Thanks fge. I used eval command in front of "java" command (eval java ${D_ARG} TestProgram) which solved my problem. Thanks for you time.
0

You may possibly escape the spaces in "/Path /To A/File". This is however not a good solution, because many a times, we may formulate a command like

system(argv[1]);/* Example is  C specific; 
      but you understand the loop-hole imparted by single escaping.
      You may require multilevel escaping, based on your implementation. OR
      We may have to escape the string, every time it is dereferenced.
      */

Better options on linux systems is to create a symbolic link.

ln -s "/Path /To A/File" /tmp/file

& then in argument file, use -Dargument1="/tmp/file"
Use this approach, if there is only one file "/Path /To A/File" in question.


Another approach is using mount --bind

mkdir /tmp/myfiles && mount --bind "/Path /To A" /tmp/myfiles

& then in argument file, use -Dargument1="/tmp/myfiles/File"
This approach would mount "/Path /To A" to /tmp/myfiles. All the files & directory structure in it will be retained.

Comments

0

The script worked when used with the command eval, which preserves quotes and it didn't add any additional single quotes.

  D_ARG=`(tr '\r\n' ' ' < argument.dat)
 \#executing java code by passing above argument
  eval java ${D_ARG} TestProgram

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.