Files
2026-06-03 15:49:54 -05:00

170 lines
4.4 KiB
Markdown

# text-shark
A Go CLI for fast text search, in-place replacement, line deletion, and file deletion. Powered by [`rg`](https://github.com/BurntSushi/ripgrep) for content operations and [`fd`](https://github.com/sharkdp/fd) for file-name finding.
## Prerequisites
- [ripgrep](https://github.com/BurntSushi/ripgrep) (`rg`)
- [fd](https://github.com/sharkdp/fd) (`fd`)
- Go 1.21+ (to build from source)
**Install on Ubuntu/Debian:**
```sh
sudo apt install ripgrep fd-find
```
**Install on macOS:**
```sh
brew install ripgrep fd
```
## Installation
```sh
git clone https://github.com/jasonross/text-shark
cd text-shark
go build -o text-shark .
```
Move the binary somewhere on your `$PATH`:
```sh
mv text-shark /usr/local/bin/
```
## Commands
### `find`
Search for a pattern in file contents. Output is streamed directly from `rg`, preserving colors and formatting.
```sh
text-shark find <pattern> [path]
```
```sh
text-shark find 'TODO'
text-shark find 'TODO' ./src
text-shark find -i 'error' # case-insensitive
text-shark find -t go 'context' # Go files only
text-shark find -g '*.json' 'port' # glob filter
text-shark find -F 'foo.bar' # literal string (no regex)
```
| Flag | Description |
|------|-------------|
| `-i`, `--ignore-case` | Case-insensitive search |
| `-F`, `--fixed-strings` | Treat pattern as a literal string |
| `-t`, `--type` | File type filter (e.g. `go`, `py`, `js`) |
| `-g`, `--glob` | Glob pattern for file paths |
---
### `replace`
Replace all occurrences of a string (or regex) in matching files. Reports each modified file and the line numbers that changed.
```sh
text-shark replace <from> <to> [path]
```
```sh
text-shark replace 'foo' 'bar'
text-shark replace 'foo' 'bar' ./src
text-shark replace 'foo' 'bar' --dry-run # preview changes without writing
text-shark replace -r 'foo\d+' 'item' ./src # regex mode
text-shark replace -t go 'oldPkg' 'newPkg' # Go files only
```
**Example output:**
```
./internal/config.go: lines 12, 47
./cmd/root.go: lines 3
2 file(s) modified.
```
| Flag | Description |
|------|-------------|
| `--dry-run` | Print what would change without writing files |
| `-r`, `--regex` | Treat `<from>` as a regular expression |
| `-t`, `--type` | File type filter |
| `-g`, `--glob` | Glob pattern for file paths |
---
### `delete-line`
Delete all lines containing a pattern. Reports each modified file and the original line numbers that were removed.
```sh
text-shark delete-line <pattern> [path]
```
```sh
text-shark delete-line 'debug'
text-shark delete-line 'debug' ./src
text-shark delete-line 'debug' --dry-run
text-shark delete-line -r '^#.*TODO' ./src # regex mode
text-shark delete-line -t py 'print(' ./lib # Python files only
```
**Example output:**
```
./internal/server.go: deleted lines 5, 23
./cmd/run.go: deleted lines 1
2 file(s) modified, 3 line(s) deleted.
```
| Flag | Description |
|------|-------------|
| `--dry-run` | Print what would change without writing files |
| `-r`, `--regex` | Treat pattern as a regular expression |
| `-t`, `--type` | File type filter |
| `-g`, `--glob` | Glob pattern for file paths |
---
### `find-delete-files`
Find files by **name pattern** using `fd`, display the full candidate list, then prompt for a single group confirmation before deleting.
```sh
text-shark find-delete-files <pattern> [path]
```
```sh
text-shark find-delete-files '_backup'
text-shark find-delete-files '_backup' ./archive
text-shark find-delete-files '_backup' --yes # skip prompt (scripting)
text-shark find-delete-files '\.log$' -t f ./logs # files only, regex name
```
**Example output:**
```
Found 3 file(s):
./archive/data_backup.csv
./archive/config_backup.json
./logs/old_backup.log
Delete these 3 file(s)? [y/N] y
3 file(s) deleted.
```
| Flag | Description |
|------|-------------|
| `-y`, `--yes` | Skip confirmation prompt and delete all matches |
| `-t`, `--type` | fd type filter: `f` (file), `d` (dir), `l` (symlink) — defaults to `f` |
---
## Notes
- All `replace` and `delete-line` writes are **atomic**: changes are written to a temp file in the same directory, then renamed into place, so a failure mid-write cannot corrupt the original.
- `path` defaults to `.` (current directory) on all subcommands. All operations are recursive.
- `replace` and `delete-line` use `rg -l` internally to skip files that don't contain the pattern before doing any I/O.
## Running Tests
```sh
go test ./...
```