» Make grep CLI App in Go » 2. Development » 2.8 Support Multiple File Paths

Support Multiple File Paths

If you want to support multiple file paths like this, you need to tune flag parsing logic again.

gorep pattern file1.txt file2.txt file3.txt

# Or
gorep 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. The flag module in Go won't automatically perform this expansion.
However, you can use the filepath.Glob function to manually expand the wildcard pattern.

Add multiple paths version grep in pkg/grep/search.go:

func GrepMulti(pattern string, filePaths []string, options *Options) (MatchResult, error) {
	if len(filePaths) == 0 {
		return Grep(pattern, "", options)
	}
	result := make(MatchResult)
	for _, filePath := range filePaths {
		grepResult, err := Grep(pattern, filePath, options)
		if err != nil {
			return nil, err
		}
		for k, v := range grepResult {
			result[k] = v
		}
	}
	return result, nil
}


func GrepRecursiveMulti(pattern string, dirPaths []string, options *Options) (MatchResult, error) {
	result := make(MatchResult)
	for _, dirPath := range dirPaths {
		grepResult, err := GrepRecursive(pattern, dirPath, options)
		if err != nil {
			return nil, err
		}
		for k, v := range grepResult {
			result[k] = v
		}
	}
	return result, nil
}

Modify the flag part and call multiple paths version functions in main.go:

@@ -36,9 +36,9 @@ func main() {
                flag.Usage()
                os.Exit(0)
        }
-       pattern, filePath := args[0], ""
+       pattern, filePaths := args[0], []string{}
        if len(args) > 1 {
-               filePath = args[1]
+               filePaths = args[1:]
        }
 
        options := &grep.Options{}
@@ -52,13 +52,13 @@ func main() {
        var result grep.MatchResult
        var err error
 
-       if *recursiveFlag && filePath != "" {
-               result, err = grep.GrepRecursive(pattern, filePath, options)
+       if *recursiveFlag && len(filePaths) > 0 {
+               result, err = grep.GrepRecursiveMulti(pattern, filePaths, options)
                if err != nil {
                        log.Fatal("Failed to do recursive grep, error:", err)
                }
        } else {
-               result, err = grep.Grep(pattern, filePath, options)
+               result, err = grep.GrepMulti(pattern, filePaths, options)
                if err != nil {
                        log.Fatal("Failed to grep, error:", err)
                }

Then you can do this:

gorep -n result pkg/grep/*go

# Or
gorep -n result pkg/grep/search.go pkg/grep/search_test.go

Result:

pkg/grep/search.go:
31: result := make(MatchResult)
38: result[k] = v
41: return result, nil
75: func GrepCount(result MatchResult) int {
77: for _, v := range result {
84: result := make(MatchResult)
91: result[k] = v
94: return result, nil
98: results := make(MatchResult)
105: result, grepErr := Grep(pattern, filePath, options)
109: results[filePath] = result[filePath]
116: return results, nil

pkg/grep/search_test.go:
32: result, err := Grep(pattern, tmpfile.Name(), options)
42: if !reflect.DeepEqual(result, expectedResult) {
43: t.Errorf("Expected %v, but got %v", expectedResult, result)
50: result := make(MatchResult)
51: count := GrepCount(result)
59: result := MatchResult{
68: count := GrepCount(result)
108: result, err := GrepRecursive(pattern, tmpdir, options)
127: if !reflect.DeepEqual(result, expectedResult) {
128: t.Errorf("Expected %v, but got %v", expectedResult, result)

Congratulations🎉! You've made a great CLI app in Go now.

Complete code: https://github.com/Literank/lr_gorep

Keep Going! Keep Learning!

PrevNext