{"id":51526731,"url":"https://github.com/kithuto/grep-for-windows","last_synced_at":"2026-07-08T22:01:39.724Z","repository":{"id":356076671,"uuid":"1230926547","full_name":"kithuto/grep-for-windows","owner":"kithuto","description":"Linux-style grep for Windows PowerShell literal and regex search in one command, no binaries, no dependencies, just drop it into your $PROFILE.","archived":false,"fork":false,"pushed_at":"2026-05-06T13:13:19.000Z","size":15,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-06T15:26:03.328Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PowerShell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kithuto.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-06T13:05:37.000Z","updated_at":"2026-05-06T14:01:43.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/kithuto/grep-for-windows","commit_stats":null,"previous_names":["kithuto/grep-for-windows"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/kithuto/grep-for-windows","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kithuto%2Fgrep-for-windows","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kithuto%2Fgrep-for-windows/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kithuto%2Fgrep-for-windows/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kithuto%2Fgrep-for-windows/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kithuto","download_url":"https://codeload.github.com/kithuto/grep-for-windows/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kithuto%2Fgrep-for-windows/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35279442,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-08T02:00:06.796Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-08T22:01:37.573Z","updated_at":"2026-07-08T22:01:39.647Z","avatar_url":"https://github.com/kithuto.png","language":"PowerShell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# grep-for-windows\n\n\u003e Linux-style `grep` for PowerShell — same flags, same defaults, same colored output.\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n[![PowerShell](https://img.shields.io/badge/PowerShell-5.1%2B%20%7C%207%2B-5391FE?logo=powershell)](https://learn.microsoft.com/powershell/)\n[![Platform](https://img.shields.io/badge/platform-Windows-0078D6)](#requirements)\n\n`grep-for-windows` is a small PowerShell module that gives you the GNU `grep`\ncommand you already know. If you came to Windows from Linux or macOS and miss\ntyping `grep -rn \"TODO\" .` instead of `Get-ChildItem | Select-String`, this is\nfor you. No external binaries, no `git-bash`, no WSL — just one module that\nplugs into your existing PowerShell.\n\n```powershell\n# Find every TODO in your project, with line numbers\ngrep -rn \"TODO\" .\n\n# Filter a log file for errors as it grows\nGet-Content .\\app.log -Wait | grep -i \"error\"\n\n# Extract every email address in a directory tree\ngrep -r -o -e \"[\\w.+-]+@[\\w-]+\\.[\\w.-]+\" .\n\n# Show the function definitions in a script, with two lines of context\ngrep -B 1 -A 2 \"^function\" .\\script.ps1\n```\n\n---\n\n## Contents\n\n- [Install](#install)\n- [Requirements](#requirements)\n- [Features](#features)\n- [Usage](#usage)\n- [Reference](#reference)\n- [Output format](#output-format)\n- [Configuration](#configuration)\n- [Update](#update)\n- [Uninstall](#uninstall)\n- [Manual install](#manual-install-without-the-script)\n- [Compatibility notes](#compatibility-notes)\n- [Contributing](#contributing)\n- [License](#license)\n\n---\n\n## Install\n\nRun this one-liner in any PowerShell session:\n\n```powershell\niex (irm \"https://raw.githubusercontent.com/kithuto/grep-for-windows/main/Install-GrepForWindows.ps1\")\n```\n\nThe installer:\n\n1. Downloads the module to your standard modules folder\n   (`~\\Documents\\PowerShell\\Modules\\grep-for-windows\\` on PowerShell 7+, or\n   `~\\Documents\\WindowsPowerShell\\Modules\\…` on Windows PowerShell 5.1).\n2. Loads the module in the current session, so `grep` works **immediately** —\n   no shell restart needed.\n\nYour `$PROFILE` is **not** modified. PowerShell's automatic module loading\npicks `grep` up the first time you run it in any new session.\n\nRe-running the same one-liner updates to the latest version, or no-ops if\nyou're already up to date.\n\n\u003e `irm` (`Invoke-RestMethod`) downloads the script and `iex`\n\u003e (`Invoke-Expression`) runs it. If you'd rather inspect first:\n\u003e `irm \u003curl\u003e -OutFile Install-GrepForWindows.ps1`, review, then\n\u003e `. .\\Install-GrepForWindows.ps1`.\n\n## Requirements\n\n- Windows 10 or later\n- Windows PowerShell **5.1** or PowerShell **7+**\n\n---\n\n## Features\n\n- **Familiar syntax.** `grep -rni \"error\" .` does what you'd expect.\n- **Regex patterns by default.** Use `-F` / `--fixed-strings` to match literal text instead of a regex. Use `-e PATTERN` (repeatable) for multiple patterns.\n- **Reads from pipes.** `Get-Content app.log | grep -i \"error\"` works out of the box.\n- **Recursive search** with directory and glob filters (`-r`, `--include`, `--exclude`, `--exclude-dir`).\n- **Context lines** around each match (`-A`, `-B`, `-C`).\n- **Counting and listing** (`-c`, `-l`).\n- **Invert, word-match, only-matching** (`-v`, `-w`, `-o`).\n- **Streaming output.** Hits print the moment they're found, just like real `grep`.\n- **Colored output.** File paths in magenta, matches in red, context lines kept plain.\n- **GNU grep defaults.** Path shown only on multi-file/recursive search; line numbers off unless `-n`.\n- **Zero dependencies.** Pure PowerShell, no external binaries.\n\n---\n\n## Usage\n\n### Search a file or directory\n\n```powershell\ngrep \"TODO\" .\\notes.txt              # single file → just the matching lines\ngrep \"TODO\" .                        # directory → path-prefixed matches\ngrep -r \"TODO\" .                     # recursive\ngrep -ri \"todo\" .                    # case-insensitive\ngrep -rn \"TODO\" .                    # show line numbers\n```\n\n### Read from stdin (pipes)\n\n```powershell\n\"hello\",\"world\" | grep \"world\"\nGet-Content .\\app.log | grep -i \"error\"\nGet-Content .\\app.log -Wait | grep -i \"error\"   # follow the file\n```\n\n### Recurse with filters\n\n```powershell\ngrep -r \"TODO\" . --include=\"*.md\" --include=\"*.txt\" --exclude=\"*.bak\"\ngrep -r \"TODO\" --exclude-dir=node_modules --exclude-dir=.git\ngrep -r \"TODO\" --include=\"*.{md,txt}\" --exclude=\"*.bak\"\n```\n\n### Context around matches\n\n```powershell\ngrep -A 2 \"function grep\" .\\script.ps1     # 2 lines after each match\ngrep -B 1 \"throw\" .\\error.ps1              # 1 line before each match\ngrep -C 3 \"ERROR\" .\\big.log                # 3 lines on either side\n```\n\nContext lines use a `-` separator (e.g., `42-...`) instead of `:`, so match\nlines remain easy to spot even in dense output.\n\n### Counts and file lists\n\n```powershell\ngrep -c \"TODO\" .\\notes.txt           # count matching lines in one file\ngrep -rc \"TODO\" .                    # per-file counts, recursive\ngrep -rl \"function\" . --include=\"*.ps1\"   # just print files that contain a match\n```\n\n### Invert, word-match, only-matching\n\n```powershell\ngrep -v \"DEBUG\" .\\app.log            # lines that do NOT contain \"DEBUG\"\ngrep -w \"grep\" .\\README.md           # whole-word match\ngrep -o -e \"[\\w]+@[\\w.-]+\" .\\file    # print only the matched substrings\n```\n\n### Multiple patterns with `-e`\n\n`-e PATTERN` is repeatable; matches are combined with OR.\n\n```powershell\ngrep -e \"TODO\" -e \"FIXME\" .\\notes.txt           # any line matching either\ngrep -r -e \"^function\" -e \"^class\" .\\src        # function OR class headers\n```\n\n### Literal (fixed-string) search with `-F`\n\nBy default the pattern is a .NET regex. Use `-F` to treat it as plain text — useful when the search term contains regex metacharacters like `.`, `*`, `(`, `)`, etc.\n\n```powershell\ngrep -F \"1.2.3\" .\\CHANGELOG.md       # literal dots, not \"any char\"\ngrep -rF \"arr[0]\" .                  # literal brackets\ngrep -Fi \"hello world\" .             # literal + case-insensitive\n```\n\n### Patterns starting with `-`\n\nUse `-e` so the pattern is parsed as the option's argument, or place a bare `-` before the pattern to stop option parsing (analogous to `--` in GNU `grep` — note that `grep-for-windows` uses a single `-` for this, not `--`). With `-F`, no workaround is needed.\n\n```powershell\ngrep -e \"-RestMethod\" .              # -e takes the pattern directly\ngrep -r - '-RestMethod' .            # bare - stops option parsing; -RestMethod is the pattern\ngrep -rF '-RestMethod' .             # -F: no workaround needed\n```\n\n---\n\n## Reference\n\nThe full option list, mirroring GNU `grep` where it makes sense.\n\n### General\n\n| Option | Description |\n|---|---|\n| `--help` | Show the help banner and exit. |\n| `-V`, `--version` | Print the installed version and exit. |\n| `--update` | Re-run the installer to fetch the latest version from GitHub. |\n\n### Pattern selection\n\n| Option | Description |\n|---|---|\n| `-e PAT`, `--regexp=PAT` | Use `PAT` as a regex pattern. Repeatable: multiple `-e` patterns are combined as an OR alternation. The first positional arg becomes the path. |\n| `-F`, `--fixed-strings` | Interpret the pattern (and any `-e` patterns) as literal text — regex metacharacters are matched verbatim. |\n| `-i`, `--ignore-case` | Case-insensitive match. |\n| `-w`, `--word-regexp` | Match whole words only (wraps the pattern with `\\b`). |\n| `-x`, `--line-regexp` | Match only whole lines (the pattern must match the entire line). |\n| `-v`, `--invert-match` | Print lines that do **not** match. |\n\n### Output control\n\n| Option | Description |\n|---|---|\n| `-n`, `--line-number` | Prefix each match with its line number. |\n| `-c`, `--count` | Print only a count of matching lines per file. |\n| `-l`, `--files-with-matches` | Print only the names of files that contain matches. |\n| `-L`, `--files-without-match` | Print only the names of files with **no** matches. |\n| `-o`, `--only-matching` | Print only the matched portion of a line, one match per output line. |\n| `-q`, `--quiet`, `--silent` | Suppress all output; exit `0` on the first match, `1` if none. |\n| `-s`, `--no-messages` | Suppress error messages about unreadable files (e.g. `Permission denied`). The exit code still reflects errors (`2`), matching GNU `grep`. |\n| `-m NUM`, `--max-count=NUM` | Stop after `NUM` matching lines per file. |\n\n### Context\n\n| Option | Description |\n|---|---|\n| `-A NUM`, `--after-context=NUM` | Print `NUM` lines after each match. |\n| `-B NUM`, `--before-context=NUM` | Print `NUM` lines before each match. |\n| `-C NUM`, `--context=NUM` | Print `NUM` lines of context (before and after). |\n| `-NUM` | Shortcut for `-C NUM` (e.g. `-3` prints 3 lines of context). |\n\n`-A`/`-B`/`-C` can be combined; `-A NUM` and `-B NUM` override `-C` when both are given.\n\n### File traversal\n\n| Option | Description |\n|---|---|\n| `-r`, `--recursive` | Recurse into subdirectories. |\n| `--include=GLOB` | Include only files whose name matches `GLOB`. Repeatable. |\n| `--exclude=GLOB` | Skip files whose name matches `GLOB`. Repeatable. |\n| `--exclude-dir=NAME` | Skip any directory named `NAME`. Repeatable. |\n\n### Arguments\n\n| Argument | Description |\n|---|---|\n| `\u003cpattern\u003e` | Required. The text or regex to search for. |\n| `[path]` | Optional. File or directory to search. Defaults to `.`. Use `-` (or pipe) to read from stdin. |\n\n---\n\n## Output format\n\n`grep-for-windows` follows GNU `grep` defaults: it shows the file path only\nwhen the search spans multiple files (a directory or recursive search), and it\nprints line numbers only when you ask for them with `-n`.\n\n| Invocation | Output line |\n|---|---|\n| `grep \"x\" file.txt` | `line content` |\n| `grep -n \"x\" file.txt` | `42: line content` |\n| `grep \"x\" .` *(directory)* | `path\\file.ext:line content` |\n| `grep -rn \"x\" .` | `path\\file.ext:42: line content` |\n| `cmd \\| grep \"x\"` | `line content` |\n| `cmd \\| grep -n \"x\"` | `42: line content` |\n\n- File paths are printed in **magenta**, matches highlighted in **red**.\n- Context lines (`-A` / `-B` / `-C`) use a `-` separator instead of `:`.\n- I/O errors (unreadable file, permission denied, etc.) are reported in\n  GNU style — e.g. `grep: path\\to\\file: Permission denied` — and skipped over\n  so the search continues. Use `-s` to silence them.\n\nExit codes match GNU `grep`: `0` (match found), `1` (no match), `2` (error).\n\n---\n\n## Configuration\n\nTo skip certain folders in **every** search (e.g. `node_modules`, `.git`),\nadd `$global:GrepAlwaysExcludedDirs` to your `$PROFILE`:\n\n```powershell\n$global:GrepAlwaysExcludedDirs = @('node_modules', '.git', '__pycache__', 'dist')\n```\n\nReload (`. $PROFILE`) or open a new shell. Folders passed explicitly via\n`--exclude-dir=` on the command line are added on top of this list, never\nreplacing it.\n\nThis is the only `grep-for-windows` setting that lives in your profile — the\nmodule itself loads automatically the first time you call `grep`, no\n`Import-Module` line required.\n\n---\n\n## Update\n\n```powershell\ngrep --update\n```\n\nThat re-runs the installer, which fetches the latest manifest from GitHub.\nIf your installed version matches the remote, nothing happens. Otherwise the\nmodule files are overwritten in place and the module reloads in the current\nsession.\n\nYou can also re-run the install one-liner — same effect:\n\n```powershell\niex (irm \"https://raw.githubusercontent.com/kithuto/grep-for-windows/main/Install-GrepForWindows.ps1\")\n```\n\nCheck the installed version any time:\n\n```powershell\ngrep --version\n```\n\n---\n\n## Uninstall\n\n```powershell\nUninstall-GrepForWindows\n```\n\nThis:\n\n1. Unloads the module from the current session.\n2. Deletes the module folder from disk.\n\nIf you added `$global:GrepAlwaysExcludedDirs` to your `$PROFILE` you can leave\nit (harmless) or remove it manually. Pass `-WhatIf` to preview without\ntouching anything, or `-Confirm` to be prompted first.\n\n---\n\n## Manual install (without the script)\n\nIf you'd rather not run a remote script:\n\n1. Clone or download this repository.\n2. Copy the [`module/`](module/) folder into your modules path, naming the\n   destination folder `grep-for-windows`:\n\n   ```powershell\n   $dest = Join-Path ([Environment]::GetFolderPath('MyDocuments')) 'PowerShell\\Modules\\grep-for-windows'\n   New-Item -ItemType Directory -Path $dest -Force | Out-Null\n   Copy-Item .\\module\\* $dest -Force\n   ```\n\n   On Windows PowerShell 5.1, replace `PowerShell` with `WindowsPowerShell` in\n   the path above.\n\nThat's it. PowerShell's automatic module loading will pick up `grep` the next\ntime you call it in any new session. To use it immediately in the current\nsession: `Import-Module grep-for-windows`.\n\n---\n\n## Compatibility notes\n\n- **`-h` is not the help shortcut.** GNU `grep` reserves `-h` for `--no-filename`,\n  not help. Use `--help` (or `-?`).\n- **Patterns starting with `-`.** Use `grep -e \"-foo\" .\\file` so the pattern is\n  bound to `-e` rather than parsed as an option. PowerShell also strips bare\n  `--` before it reaches the function, so use `-` insted (`grep - \"-foo\"`) if you\n  prefer the end-of-options style.\n- **Multiple file arguments.** Currently `grep` accepts one path per\n  invocation. To search several files explicitly, point at their parent\n  directory and use `--include=GLOB`.\n\n---\n\n## Contributing\n\nIssues and pull requests are welcome at the\n[GitHub repository](https://github.com/kithuto/grep-for-windows).\n\nWhen submitting a pull request:\n\n1. Fork the repository and create a feature branch.\n2. Keep changes focused; write a clear commit message.\n3. Test on both Windows PowerShell 5.1 and PowerShell 7+ when possible.\n\n---\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkithuto%2Fgrep-for-windows","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkithuto%2Fgrep-for-windows","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkithuto%2Fgrep-for-windows/lists"}