I tweaked your type function to be more informative:
def regex_type(s, pattern=re.compile(r"[a-f0-9A-F]")): print('regex string', s) if not pattern.match(s): raise argparse.ArgumentTypeError('pattern not match') return s
Called with
2104:~/mypy$ python2 stack50072557.py .
I get:
<director list> ('regex string', '.') usage: stack50072557.py [-h] [-name [NAME [NAME ...]]] regex stack50072557.py: error: argument regex: pattern not match
So it tries to pass sys.argv[1], the first string after the script name, to the regex_type function. If it fails it issues the error message and usage.
OK, the problem was the ..; I'll make a directory:
2108:~/mypy$ mkdir foo 2136:~/mypy$ python2 stack50072557.py foo ('regex string', 'foo') Namespace(name=[<open file '<stdin>', mode 'r' at 0x7f3bea2370c0>], regex='foo') 2138:~/mypy$ python2 stack50072557.py foo -name a b c ('regex string', 'foo') Namespace(name=['a', 'b', 'c'], regex='foo')
The strings following '-name' are allocated to that attribute. There's nothing in your code that will test them or pass them through the regex_type function. Only the first non-flag string does that.
Reading sys.argv[1] initially does not remove it from the list. It's still there for use by the parser.
I would set up a parser that uses a store_true --name argument, and 2 positionals - one for the dir and the other for regex.
After parsing check args.name. If false print the contents of args.dir. If true, perform your args.regex filter on those contents. glob might be useful.
The parser finds out what your user wants. Your own code acts on it. Especially as a beginner, it is easier and cleaner to separate the two steps.
With:
def parse(argv=None): parser = argparse.ArgumentParser() parser.add_argument('-n', '--name', action='store_true') parser.add_argument('--dir', default='.') parser.add_argument('--regex', default=r"[a-f0-9A-F]") args = parser.parse_args(argv) print(args) return args def main(argv=None): args = parse(argv) dirls = os.listdir(args.dir) if args.name: dirls = [f for f in dirls if re.match(args.regex, f)] print(dirls) else: print(dirls)
I get runs like:
1005:~/mypy$ python stack50072557.py Namespace(dir='.', name=False, regex='[a-f0-9A-F]') ['test.npz', 'stack49909128.txt', 'stack49969840.txt', 'stack49824248.py', 'test.h5', 'stack50072557.py', 'stack49963862.npy', 'Mcoo.npz', 'test_attribute.h5', 'stack49969861.py', 'stack49969605.py', 'stack49454474.py', 'Mcsr.npz', 'Mdense.npy', 'stack49859957.txt', 'stack49408644.py', 'Mdok', 'test.mat5', 'stack50012754.py', 'foo', 'test'] 1007:~/mypy$ python stack50072557.py -n Namespace(dir='.', name=True, regex='[a-f0-9A-F]') ['foo'] 1007:~/mypy$ python stack50072557.py -n --regex='.*\.txt' Namespace(dir='.', name=True, regex='.*\\.txt') ['stack49909128.txt', 'stack49969840.txt', 'stack49859957.txt']
and help:
1007:~/mypy$ python stack50072557.py -h usage: stack50072557.py [-h] [-n] [--dir DIR] [--regex REGEX] optional arguments: -h, --help show this help message and exit -n, --name --dir DIR --regex REGEX
If I change the dir line to:
parser.add_argument('dir', default='.')
help is now
1553:~/mypy$ python stack50072557.py -h usage: stack50072557.py [-h] [-n] [--regex REGEX] dir positional arguments: dir optional arguments: -h, --help show this help message and exit -n, --name --regex REGEX
and runs are:
1704:~/mypy$ python stack50072557.py -n usage: stack50072557.py [-h] [-n] [--regex REGEX] dir stack50072557.py: error: too few arguments 1705:~/mypy$ python stack50072557.py . -n Namespace(dir='.', name=True, regex='[a-f0-9A-F]') ['foo'] 1705:~/mypy$ python stack50072557.py ../mypy -n --regex='.*\.txt' Namespace(dir='../mypy', name=True, regex='.*\\.txt') ['stack49909128.txt', 'stack49969840.txt', 'stack49859957.txt']
I get the error because it now requires a directory, even it is '.'.
Note that the script still uses:
if __name__ == '__main__': main()
My main loads the dir, and applies the regex filter to that list of names. My args.dir replaces your direc.