find . -name "*.md" -type f -exec sed -i '/pattern/d' {} \;

This one-liner walks the directory tree, finds every .md file, and strips out any line that matches the given pattern. The sed -i edits each file in place, and the {} gets swapped out for whatever path find hands it.

Breaking it down

find . -name "*.md" -type f does the walking. The -type f bit is important – without it, find would also match directories and pass them to sed, which would error out. The -exec ... \; at the end runs the command for each file individually.

The sed part is straightforward: /pattern/d means “delete any line matching pattern”. Replace pattern with whatever regex you need – a literal string, a word boundary, whatever suits.

A few things to watch out for

Test first. Run the find part on its own and pipe to less or wc -l to see what files would be affected before you start editing them in place:

find . -name "*.md" -type f | wc -l

BSD sed vs GNU sed. If you’re on macOS, sed -i wants an backup extension argument: sed -i '' '/pattern/d'. On Linux with GNU sed, sed -i works as-is. This catches people out more often than it should.

Backups. If you want a safety net, give sed -i a backup suffix:

find . -name "*.md" -type f -exec sed -i.bak '/pattern/d' {} \;

That leaves .bak files alongside your originals. Worth it if you’re running this against a directory you didn’t write yourself.

When the pattern is in the filename, not the content

If you actually meant “delete lines that match a string found in filenames”, that’s a different command entirely. See my post on deleting files by content match for the other interpretation.