1

I've got a bootstrap (bash) that should filter out some arguments before it starts the propper python script.

The problem is that whenever i pass a string with spaces into the bootstrap it gets mangled up once it arrives at python

e.g executing

./myBootStrap.sh --preload "argl bargl" -j -as -argl --postload "my Test"

prints this

Executing myBootStrap --preload "argl bargl" -j -as -argl --postload "my Test"

and my python script prints its argument

got arguments ['myBootStrap','--preload', '"argl', 'bargl"', '-j', '-as', '-argl', '--postload', '"my', 'Test"']

as you see the "argl bargl" and "my Test" get split up into ['"argl','bargl"'] & ['"my', 'Test"'] instead of staying combined.

any idea whats wrong with my code ?

thanks heaps!


myBootStrap.sh

#!/bin/bash
declare -a argv
for ((i=1;i<=${#@};i+=1))
do

   arg=${@:i:1}

   if [[ "$arg" == "--preload"* ]];then
      i=$i+1
      marg=${@:$((i)):1}
      preLoadO=$arg
      preLoadA=" \"${marg}\""
      argv=("${argv[@]}" $arg)
      argv=("${argv[@]}" $preLoadA)

   elif [[ "$arg" == "--postload"* ]];then
      i=$i+1
      marg=${@:$((i)):1}
      postLoadO=$arg
      postLoadA=" \"${marg}\""
      argv=("${argv[@]}" $arg)
      argv=("${argv[@]}" $postLoadA)       
   else          
      argv=("${argv[@]}" $arg)
   fi
done

arguments=$(printf " %s" "${argv[@]}")
arguments=${arguments:1}

echo "Executing myBootStrap" $arguments 
exec myBootStrap $arguments 

and the python script myBootStrap

#!/usr/bin/env python
import sys
print 'got arguments %s'%sys.argv
7
  • 1
    python has builtin capabilities for allowing you to parse command line arguments: getopt, argparse or optparse (deprecated!). do yourself a favour and use them, it's a lot easier then parsing aruments in bash using printf and manually quoting strings... Commented May 14, 2012 at 8:58
  • unfortunately i have to go through bash first, because it sets up a lot of env-variables etc, so there is no way to go around bash :( Commented May 14, 2012 at 9:00
  • then i'd recommend GNU getopt Commented May 14, 2012 at 9:18
  • @Seb: you can set environment variables in Python as well, using os.environ. Commented May 14, 2012 at 10:22
  • @mata: I wouldn't. Commented May 14, 2012 at 22:59

1 Answer 1

4

Quoting almost always fixes this type of problem.

exec myBootStrap "$arguments"

Demo:

$ a='"abc def" ghi'
$ echo "$a"
"abc def" ghi
$ args $a
3 args: <"abc> <def"> <ghi>
$ args "$a"
1 args: <"abc def" ghi>
$ cat args
#! /bin/sh
# Greg Wooledge's args script
printf "%d args:" $#
printf " <%s>" "$@"
echo

Edit:

OK, I spent some time analyzing what your Bash script is actually doing. It's going through a lot of gyrations to simply try to produce exactly the same arguments it was given and then pass them to the Python script.

It could simply be replaced by:

exec myBootStrap "$@"

However, I presume that you're actually doing some other processing there which we don't see. Based on that, I've modified your script so it can be used as a basis for something like that.

#!/bin/bash
declare -a argv
for ((i = 1; i <= $#; i += 1))
do

   arg=${@:i:1}

   if [[ "$arg" == "--preload"* ]]; then
      marg=${@: ++i:1}
      preLoadO=$arg
      preLoadA="${marg}"
      argv+=("$arg")
      argv+=("$preLoadA")

   elif [[ "$arg" == "--postload"* ]]; then
      marg=${@: ++i:1}
      postLoadO=$arg
      postLoadA="${marg}"
      argv+=("$arg")
      argv+=("$postLoadA")
   else
      argv+=("$arg")
   fi
done

exec ./myBootStrap "${argv[@]}"

The arguments must be passed as a quoted array. You had already built the array, but then you flattened it with a printf.

Note that an array slice is already an arithmetic context so you don't need $(()) inside it. I removed the separate i=i+1 (which concatenates characters so you get 1+1+1+1 after a while) and just put a pre-increment inside the array slice. The space before the first plus is required since :+ is significant inside an brace expansion. If you want, you can do the increment separately like this: ((i++)); marg=${@:i:1} (of course on separate lines if you prefer).

I changed your array appends to the much simpler += form and added quoting to them.

Sign up to request clarification or add additional context in comments.

1 Comment

unfortunately not, if you would run the python script just changing the last line from $arguments to "$arguments" the python script will still get the arguments split up

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.