git ls-files -mo --exclude-standard | grep -E 'test|bats' | xargs -i git add {}This one-liner stages only files whose paths contain test or bats, among files that are either modified or untracked (but not ignored).
🎯 Goal
🔍 Diving into the pipeline
The command is three stages glued together with pipes:
git ls-files -mo --exclude-standard # 1. list candidate files
| grep -E 'test|bats' # 2. filter by path pattern
| xargs -i git add {} # 3. stage each one1. git ls-files -mo --exclude-standard
git ls-files prints file paths that Git knows about (or could know about) in the current working tree.
| Option | Meaning |
|---|---|
-m |
Modified — tracked files that differ from the index |
-o |
Others — files in the working tree that are not tracked (i.e. untracked files) |
--exclude-standard |
Apply the usual ignore rules: .gitignore, .git/info/exclude, and the user’s global excludes file |
So -mo --exclude-standard together means “modified files plus untracked files, but skip anything that is ignored.” Deleted files are not included unless you also pass -d.
git add -u or git add .?
git add -ustages modified and deleted tracked files, but ignores untracked ones.git add .stages everything under the current directory, including files you may not want.
2. grep -E 'test|bats'
Filter the list to lines matching the extended regex test|bats — i.e. any path that contains the substring test or bats anywhere.
| Option | Meaning |
|---|---|
-E |
Use Extended Regular Expressions (so | works as alternation without backslashing) |
Example matches:
tests/test_parser.py ✅ contains "test"
src/foo.bats ✅ contains "bats"
scripts/run-bats.sh ✅ contains "bats"
src/main.py ❌ no match
grep matches anywhere in the path
The pattern test will also match latest/, contest.md, or protest.txt. Tighten the regex when in doubt — e.g. '(^|/)tests?/' to require a literal tests/ or test/ directory segment.
3. xargs -i git add {}
xargs builds and executes commands from stdin. Here it runs git add <file> once per line of input.
| Option | Meaning |
|---|---|
-i |
Replace {} in the command with each input line. Deprecated in GNU xargs — prefer -I {} (capital I). |
{} |
Placeholder for the current input line |
So for input lines a.py, b.py, xargs runs:
git add a.py
git add b.pyThe portable, modern equivalent is:
git ls-files -mo --exclude-standard -z \
| grep -zE 'test|bats' \
| xargs -0 -I {} git add {}-z/-0use NUL-delimited records, so paths containing spaces, tabs, or newlines do not break the pipeline.-I {}is the POSIX-standard replacement form (the lowercase-iworks on GNUxargsbut is non-standard).
✅ Variations worth knowing
Stage only modified files matching a pattern (skip untracked)
git ls-files -m --exclude-standard | grep -E 'test|bats' | xargs -I {} git add {}Preview what will be staged before running git add
git ls-files -mo --exclude-standard | grep -E 'test|bats'