Support Multiple File Paths
parser.add_argument('file_paths', nargs='*', default=[], help='File paths to search in')
nargs='*'
allows the script to accept zero or more file paths.
Then you can do this:
grepy pattern file1.txt file2.txt file3.txt
# Or
grepy pattern *.txt
Note:
Using*.txt
as an argument in the command line directly may not work as expected because the shell (e.g., Bash) is responsible for expanding wildcard patterns like*.txt
. Theargparse
module in Python won't automatically perform this expansion.
However, you can use theglob
module to manually expand the wildcard pattern.
Add multiple paths version grep
in grepy/grep.py:
def grep_m(pattern: Union[str, re.Pattern],
file_paths: Union[List[str], Literal['']], options: List[str]):
"grep multiple files"
if not file_paths:
return grep(pattern, "", options)
result = {}
for file_path in file_paths:
result.update(grep(pattern, file_path, options))
return result
def grep_recursive_m(pattern: Union[str, re.Pattern],
file_paths: Union[List[str], Literal['']], options: List[str]):
"grep multiple dirs recursively"
result = {}
for file_path in file_paths:
result.update(grep_recursive(pattern, file_path, options))
return result
Modify the argparse
part in grepy/cli.py:
@@ -1,16 +1,16 @@
import argparse
from typing import List, Dict
-from grepy.grep import grep, grep_recursive, grep_count, MatchResults
+from grepy.grep import grep_recursive_m, grep_count, grep_m, MatchResults
def main():
parser = argparse.ArgumentParser(description='''
A grep-like command-line utility from LiteRank,
see https://literank.com/project/9/intro''')
parser.add_argument('pattern', type=str, help='The pattern to search for')
- parser.add_argument('file_path', type=str, nargs="?", default="",
- help='The path to the file to search in')
+ parser.add_argument('file_paths', nargs="*", default=[],
+ help='File paths to search in')
# Optional arguments
parser.add_argument('-c', '--count', action='store_true',
@@ -31,11 +31,11 @@ def main():
args = parser.parse_args()
- if args.recursive and args.file_path != "":
- result = grep_recursive(args.pattern,
- args.file_path, get_options(args))
+ if args.recursive and args.file_paths != "":
+ result = grep_recursive_m(args.pattern,
+ args.file_paths, get_options(args))
else:
- result = grep(args.pattern, args.file_path, get_options(args))
+ result = grep_m(args.pattern, args.file_paths, get_options(args))
if args.count:
print(grep_count(result))
Then you can do this:
grepy -n result grepy/*py
# Or
grepy -n result grepy/cli.py grepy/grep.py
Result:
grepy/cli.py:
35: result = grep_recursive_m(args.pattern,
38: result = grep_m(args.pattern, args.file_paths, get_options(args))
41: print(grep_count(result))
43: print_result(result, args.line_number)
55: def print_result(result: Dict[str, MatchResults], line_number_option: bool):
57: file_count = len(result)
58: for file_path, lines in result.items():
grepy/grep.py:
21: result = {}
23: result.update(grep(pattern, file_path, options))
24: return result
51: def grep_count(result: Dict[str, MatchResults]):
52: return sum([len(v) for v in result.values()])
58: result = {}
60: result.update(grep_recursive(pattern, file_path, options))
61: return result
66: results = {}
70: results.update(grep(pattern, file_path, options))
71: return results
Nice👍🏻! So far so good!