Coleman McFarland's Blog

The nouveau command line text trifecta: ripgrep, sd, fd

Here are three programs I always install.

ripgrep

A very fast way to search through text files for a string pattern.

It has tons of options, but I use a few flags all the time.

For example, the following will print all instances of func init() in files with a ".go" extension.

rg -F 'func init()' -g '*.go'

Take note of the single quotes for the glob argument. You'll probably need those.

The -g flag can also be prefixed with ! to ignore files that match a pattern. Our previous example can be modified to ignore test files.

rg -F 'func init()' -g '!*_test.go` -g '*.go'

fd

This one has a different job. Ripgrep searches for patterns inside text files, but fd searches for files based on patterns in filenames.

By default it prints the filepath of every file recursively, one file per line. This gives you a way to count the number of files in a directory.

fd | wc -l

Hidden files are ignored by default, as are patterns listed in .gitignore files. Include them with -H and -I, respectively.

fd -H -I | wc -l

Another flag I often use is -e. This limits the search by file extension and can be specified multiple times. Here we search recursively for all txt and html files.

fd -e html -e txt

fd is sometimes available as fd-find or fdfind in package managers.

sd

The sd command does find + replace. It modifies the files in-place by default. This is potentially dangerous, so only do that if you're using version control.

I always use the -F flag to search for a literal string and replace it with another literal string. This example replaces every instance of "yes" with "no" in three text files.

sd -F 'yes' 'no' one.txt two.txt three.txt

If you need to file and replace over a lot of files, you can use fd to generate the list of filepaths.

The previous example, but for every txt file in our project.

sd -F 'yes' 'no' $(fd -e txt)

sd supports regular expressions, too.

#shell