Saving spaces in a string as a command line argument

I ran into a little problem here, I want to pass a line containing spaces to another program, so the whole line is treated as a command line argument.

In short, I want to execute a command of the following structure through a bash shell script: command_name -a arg1 -b arg2 -c "arg with spaces here"

But no matter how I try, spaces are not stored in the string and are indicated by characters by default. Solution please

edit: This is the main part of my script:

#!/bin/bash #-------- BLACKRAY CONFIG ---------------# # Make sure the current user is in the sudoers list # Running all instances with sudo BLACKRAY_BIN_PATH='/opt/blackray/bin' BLACKRAY_LOADER_DEF_PATH='/home/crozzfire' BLACKRAY_LOADER_DEF_NAME='load.xml' BLACKRAY_CSV_PATH='/home/crozzfire' BLACKRAY_END_POINT='default -p 8890' OUT_FILE='/tmp/out.log' echo "The current binary path is $BLACKRAY_BIN_PATH" # Starting the blackray 0.9.0 server sudo "$BLACKRAY_BIN_PATH/blackray_start" # Starting the blackray loader utility BLACKRAY_INDEX_CMD="$BLACKRAY_BIN_PATH/blackray_loader -c $BLACKRAY_LOADER_DEF_PATH/$BLACKRAY_LOADER_DEF_NAME -d $BLACKRAY_CSV_PATH -e "\"$BLACKRAY_END_POINT\""" sudo time $BLACKRAY_INDEX_CMD -a $OUT_FILE #--------- END BLACKRAY CONFIG ---------# 
+7
scripting bash whitespace
source share
6 answers

You encountered this problem because you are storing the command in a variable and then expanding it later; if there is no good reason for this, do not do this:

 sudo time $BLACKRAY_BIN_PATH/blackray_loader -c $BLACKRAY_LOADER_DEF_PATH/$BLACKRAY_LOADER_DEF_NAME -d $BLACKRAY_CSV_PATH -e "$BLACKRAY_END_POINT" -a $OUT_FILE 

If you really need to save the command and use it later, there are several options; The bash -hackers.org wiki has a good related page . It seems to me that the most useful here is placing the command in an array, rather than a simple variable:

 BLACKRAY_INDEX_CMD=($BLACKRAY_BIN_PATH/blackray_loader -c $BLACKRAY_LOADER_DEF_PATH/$BLACKRAY_LOADER_DEF_NAME -d $BLACKRAY_CSV_PATH -e "$BLACKRAY_END_POINT") sudo time "${BLACKRAY_INDEX_CMD[@]}" -a $OUT_FILE 

This allows you to avoid confusion between word-delimiter-words and spaces in words, because words are not separated by spaces - they are in separate elements of the array. Expanding the array in double quotes with the suffix [@] preserves this structure.

(BTW, another option is to use escaped quotes just like you, and then run the command using eval . Don't do this, this is a good way to introduce strange parsing errors.)

+5
source share

I have a suggestion:

 # iterate through the passed arguments, save them to new properly quoted ARGS string while [ -n "$1" ]; do ARGS="$ARGS '$1'" shift done # invoke the command with properly quoted arguments my_command $ARGS 
+3
source share

perhaps you need to surround the argument with double quotes (for example, "$ {6}").

After the comment OP should be "$ BLACKRAY_END_POINT"

+1
source share

Edit

Try:

 BLACKRAY_END_POINT="'default -p 8890'" 

or

 BLACKRAY_END_POINT='"default -p 8890"' 

or

 BLACKRAY_END_POINT="default\ -p\ 8890" 

or

 BLACKRAY_END_POINT='default\ -p\ 8890' 

and

 BLACKRAY_INDEX_CMD="$BLACKRAY_BIN_PATH/blackray_loader -c $BLACKRAY_LOADER_DEF_PATH/$BLACKRAY_LOADER_DEF_NAME -d $BLACKRAY_CSV_PATH -e $BLACKRAY_END_POINT" 

Original answer :

Is blackray_loader a shell script?

Here is a demonstration that you should deal with this problem both when specifying a parameter and when processing it:

A text file called test.txt (including line numbers):

 1 two words 2 two words 3 two 4 words 

A script called "spacetest":

 #!/bin/bash echo "No quotes in script" echo $1 grep $1 test.txt echo echo "With quotes in script" echo "$1" grep "$1" test.txt echo 

Launch with ./spacetest "two--------words" (replace hyphens with spaces):

 No quotes in script two words grep: words: No such file or directory test.txt:1 two words test.txt:2 two words test.txt:3 two With quotes in script two words 2 two words 

You can see that in the “No quotes” section, he tried to make grep two words test.txt , which interpreted the “words” as a file name in addition to “test.txt”. In addition, echo dropped extra spaces.

When a parameter is quoted, as in the second section, grep saw it as a single argument (including extra spaces) and processed it correctly. And echo kept extra spaces.

I used extra spaces, by the way, just to help with the demo.

+1
source share

The following is an example of restarting a script via exec su USER or exec su - USER . It contains:

  • called from relative path or current working directory
  • spaces in script name and arguments
  • single and double quotes in arguments, without crazy escapes like: \\ "

 # # This script should always be run-as a specific user # user=jimbob if [ $(whoami) != "$user" ]; then exec su -c "'$(readlink -f "$0")' $(printf " %q" "$@")" - $user exit $? fi 
0
source share

Another blog post saved me for this problem with spaces: http://logbuffer.wordpress.com/2010/09/23/bash-scripting-preserve-whitespaces-in-variables/

By default, spaces are truncated:

 bash> VAR1="abc def gh ijk" bash> echo $VAR1 abc def gh ijk bash> 

"The reason for this behavior is the internal shell variable $ IFS (Internal Field Separator) , by default it is a space, tab and new line. To save all adjacent spaces , you must set IFS to something else

With IFS :

 bash> IFS='%' bash> echo $VAR1 abc def gh ijk bash>unset IFS bash> 

It works fine for my case:

 su - user1 -c 'test -r "'${filepath}'"; ....' 

Hope this helps.

-one
source share

All Articles