7

I currently have a script, which uses file globbing via the sys.argv variable like this:

if len(sys.argv) > 1:
        for filename in sys.argv[1:]:

This works great for processing a bunch of files; however, I would like to use this with the argparse module as well. So, I would like my program to be able to handle something like the following:

foo@bar:~$ myScript.py --filter=xyz *.avi

Has anyone tried to do this, or have some pointers on how to proceed?

2
  • 1
    partial parsing with argparse? Commented Dec 7, 2011 at 23:11
  • 1
    You should get rid of the len(sys.argv) stuff and just let argparse interact with sys.argv, the functionality is in there. Commented Dec 7, 2011 at 23:27

2 Answers 2

18

If I got you correctly, your question is about passing a list of files together with a few flag or optional parameters to the command. If I got you right, then you just must leverage the argument settings in argparse:

File p.py

import argparse

parser = argparse.ArgumentParser(description='SO test.')
parser.add_argument('--doh', action='store_true')
parser.add_argument('files', nargs='*')  # This is it!!
args = parser.parse_args()
print(args.doh)
print(args.files)

The commented line above inform the parser to expect an undefined number >= 0 (nargs ='*') of positional arguments.

Running the script from the command line gives these outputs:

$ ./p.py --doh *.py
True
['p2.py', 'p.py']
$ ./p.py *.py
False
['p2.py', 'p.py']
$ ./p.py p.py
False
['p.py']
$ ./p.py 
False
[]

Observe how the files will be in a list regardless of them being several or just one.

HTH!

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

4 Comments

How would you do the same thing but for a flag? I have parser.add_argument('-b', '--blacklist', nargs='*' and I'd like to pass *.mp3 into the program from the shell. Also, blacklist is used in os.walk, so the actual mp3 files won't be in working directory.
@p014k - I'm not sure I got your question. Do you want to pass a list of files using the asterisk [*] wildcard but without letting the shell making the expansion for you? If that's the case, you have to quote the argument: ./p.py --doh '*.py'. From within the p.py script you will have to use fnmatch to do the expansion for you. Or did I misunderstand you?
The arguments passed into blacklist are a set. This set is then used in for follow manner: for filename in [f for f in filenames if f not in blacklist]: within an os.walk I'd like to be able to pass *.mp3 into -b and have all mp3 files be ignored in that for loop.
@p014k - It sounds to me like yours is a separate, unrelated question relative to how to exclude mp3 files from an os.walk loop then (or am I misunderstanding you again?). From what I got from your comment above I would simply use the builtin function filter on the list returned by os.walk. Something like filter(lambda fn: fn[-3:] != 'mp3', list_of_files) (untested). HTH, but in case it doesn't, you're better opening your own question! :)
3

Alternatively you may use both in the following way:

import sys
import argparse
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("-v", "--verbose", help="increase verbosity", action="store_true")
    args, unknown = parser.parse_known_args()
    for file in sys.argv:
        if not file.startswith("-"):
            print(file)

However this will work only for standalone parameters, otherwise the argument values would be treated as file arguments (unless you'll not separate them with space or you'll improve the code further more).

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.