Search code examples
bashcommand-lineopenscad

Openscad -D command line cannot be called from shell script


I am using openscad commands on Ubuntu linux to generate models from command line. I finaly was successful at running openscad commands using the -D parameters to override variables values :

$ openscad -o output.stl -D 'param1="name1"' -D 'param2="name2"' openscad-script.scad

EDIT: Notice the way we have to pass -D parameters, both single quotes and double quotes have to be there according to the because the Openscad documentation.

But when I generate & execute the same command from a shell script, openscad fails with error :

$ ./myscript.sh value1 value2 

ERROR: Parser error in line XX: syntax error Can't parse file 'openscad-script.scad'!

Where XX = last line of file.

Here is the bash script

#!/bin/bash
# run openscad command
param1="-D 'param1=\"$1\"'"
param2="-D 'param2=\"$2\"'"
echo "openscad -o $1-$2.stl $param1 $param2 openscad-script.scad"
openscad -o $1-$2.stl $param1 $param2 openscad-script.scad

This looks so simple I still cannot figure out what make openscad fail at running the command.

Thanks for your help,

EDIT : I found a way to make it work, may not be the best

#!/bin/bash
# run openscad command
param1="-D 'param1=\"$1\"'"
param2="-D 'param2=\"$2\"'"
command = "openscad -o $1-$2.stl $param1 $param2 openscad-script.scad"
eval $command

Solution

  • If your intended command line is:

    openscad -o name1-name2.stl -D 'param1="name1"' -D 'param2="name2"' openscad-script.scad
    

    ...then a correct script to do this would be:

    #!/bin/bash
    openscad \
      -o "$1-$2.stl" \
      -D "param1=\"$1\"" \
      -D "param2=\"$2\"" \
      openscad-script.scad
    

    ...or, if you really want to build things up over multiple lines for whatever reason:

    #!/bin/bash
    
    args=( -o "$1-$2.stl" )
    args+=( -D "param1=\"$1\"" )
    args+=( -D "param2=\"$2\"" )
    
    openscad "${args[@]}" openscad-script.scad
    

    openscad literally has no way of knowing if single-quotes or double-quotes was used at the command line, so there is no enforceable way for it to require single-quotes. Moreover, shell quoting is a character-by-character attribute! That is to say:

    'param1="name1"' # becomes the C string "param1=\"name1\""
    

    results in exactly the same string being passed as:

    param1='"name1"' # becomes the C string "param1=\"name1\"", same as above
    

    or

    param1='"'name1'"' # becomes the C string "param1=\"name1\"", same as above
    

    ...when those values are all constant. When name1 is replaced with something like $1, however, then the meaning becomes very different based on the type of quotes in use:

    set -- name1; IFS=0123456789
    "param1=\"$1\"" # becomes the C string "param1=\"name1\"", as above
    'param1="$1"'   # becomes the C string "param1=\"$1\"", not substituting name1
    
    # ...and, as an example of something to look out for:
    param1='"'$1'"'  # becomes TWO C strings, "param1=\"name" and "\"", due to bad quoting
    # ...the IFS above makes it split on numbers; by default this risk would happen with spaces