5

I'm writing a small program that's supposed to execute a command on a remote server (let's say a reasonably dumb wrapper around ssh [hostname] [command]).

I want to execute it as such:

./floep [command] 

However, I need to pass certain command lines from time to time:

./floep -v [command]

so I decided to use optparse.OptionParser for this. Problem is, I sometimes the command also has argument, which works fine if I do:

./floep -v "uname -a"

But I also want it to work when I use:

./floep -v uname -a

The idea is, as soon as I come across the first non-option argument, everything after that should be part of my command.

This, however, gives me:

Usage: floep [options] floep: error: no such option: -a

Does OptionParser support this syntax? If so: how? If not: what's the best way to fix this?

4 Answers 4

13

Try using disable_interspersed_args()

#!/usr/bin/env python from optparse import OptionParser parser = OptionParser() parser.disable_interspersed_args() parser.add_option("-v", action="store_true", dest="verbose") (options, args) = parser.parse_args() print "Options: %s args: %s" % (options, args) 

When run:

 $ ./options.py foo -v bar Options: {'verbose': None} args: ['foo', '-v', 'bar'] $ ./options.py -v foo bar Options: {'verbose': True} args: ['foo', 'bar'] $ ./options.py foo -a bar Options: {'verbose': None} args: ['foo', '-a', 'bar'] 
Sign up to request clarification or add additional context in comments.

1 Comment

Thank, you.. That's a very thorough answer and worked perfectly
1

OptionParser instances can actually be manipulated during the parsing operation for complex cases. In this case, however, I believe the scenario you describe is supported out-of-the-box (which would be good news if true! how often does that happen??). See this section in the docs: Querying and manipulating your option parser.

To quote the link above:

disable_interspersed_args()

Set parsing to stop on the first non-option. Use this if you have a command processor which runs another command which has options of its own and you want to make sure these options don’t get confused. For example, each command might have a different set of options.

Comments

1
from optparse import OptionParser import subprocess import os import sys parser = OptionParser() parser.add_option("-q", "--quiet", action="store_true", dest="quiet", default=False, help="don't print output") parser.add_option("-s", "--signal", action="store_true", dest="signal", default=False, help="signal end of program and return code") parser.disable_interspersed_args() (options, command) = parser.parse_args() if not command: parser.print_help() sys.exit(1) if options.quiet: ret = subprocess.call(command, stdout=open(os.devnull, 'w'), stderr=subprocess.STDOUT) else: ret = subprocess.call(command) if options.signal: print "END OF PROGRAM!!! Code: %d" % ret 

Comments

-1

You can use a bash script like this:

#!/bin/bash while [ "-" == "${1:0:1}" ] ; do if [ "-v" == "${1}" ] ; then # do something echo "-v" elif [ "-s" == "${1}" ] ; then # do something echo "-s" fi shift done ${@} 

The ${@} gives you the rest of the command line that was not consumed by the shift calls. To use ssh you simply change the line from ${@} to ssh ${user}@${host} ${@}

test.sh echo bla
bla

test.sh -v echo bla
-v
bla

test.sh -v -s echo bla
-v
-s
bla

1 Comment

Even though your answer might be correct, for me this is an exercise in python

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.