# [Run] 🍺 (`prun`)
`Run` is a blazingly fast, concurrent command-line utility for executing
commands across multiple directories that match a specific pattern.
It's designed as a modern, high-performance replacement for complex
`find ... -execdir` pipelines, leveraging Rust's full potential for safe,
parallel, and asynchronous operations.
[Run]: https://crates.io/crates/prun
## Key Features 🔐
- **Blazing Fast**: Drastically out-performs traditional shell equivalents by
using an optimized parallel directory walker and asynchronous command
execution.
- **Concurrent by Default**: Runs tasks in parallel using a hybrid `rayon` and
`tokio` approach to maximize CPU and I/O efficiency.
- **Intuitive Syntax**: Replaces complex `find` and `xargs` syntax with simple,
readable flags.
- **Smart Exclusion**: Comes with sensible defaults to automatically ignore
common directories like `node_modules`, `.git`, and `target`.
- **Cross-Platform**: Built with Rust, `Run` works consistently across Windows,
macOS, and Linux.
---
## Performance Benchmarks 🚤
`Run` is significantly faster than its `find -execdir` equivalent. The
benchmarks below were performed on a Windows machine with an NVMe SSD and 6 core
CPU (AMD Ryzen 5 5500) with 32 GB of DDR4 RAM, scanning a large developer
directory with hundreds of Git repositories.
<table>
<tr>
<th>Command:</th>
<th>Time:</th>
</tr>
<tr>
<td>
<pre>Run -P .git -C 'ls'</pre>
</td>
<td>
<pre>real 0m3.484s
user 0m0.045s
sys 0m0.031s</pre>
</td>
</tr>
<tr>
<td>
<pre>Run -P .git -C 'git status'</pre>
</td>
<td>
<pre>real 0m7.412s
user 0m0.045s
sys 0m0.031s</pre>
</td>
</tr>
<tr>
<td>
<pre>find -iname .git -execdir ls \;</pre>
</td>
<td>
<pre>real 0m10.562s
user 0m3.092s
sys 0m6.789s</pre>
</td>
</tr>
<tr>
<td>
<pre>find -iname .git -execdir git status \;</pre>
</td>
<td>
<pre>real 0m30.352s
user 0m3.218s
sys 0m7.286s</pre>
</td>
</tr>
</table>
**Why is it so much faster?**
- `find` executes commands sequentially, one after another.
- `Run` walks the directory tree once and then executes all commands in
parallel, taking full advantage of modern multi-core processors and fast I/O.
---
## Installation 🚀
You can install `Run` directly from [Crates.io](https://crates.io/crates/prun)
using Cargo:
```sh
cargo install prun
```
The installed binary is `Run`. You may want to create a symlink or alias like
`prun` for convenience.
---
## Usage ⚙️
The core idea is to define a `Pattern` (like a file or directory name) that
identifies the locations where you want to execute one or more `Command`s.
```
A utility to run commands in directories matching a pattern.
Usage: Run [OPTIONS] --Pattern <PATTERN> --Command <COMMAND>...
Options:
-F, --File Target files directly instead of directories containing a pattern
-P, --Parallel Execute commands in parallel across all found directories
-R, --Root <DIRECTORY> The root directory to start the search from [default: .]
-E, --Exclude <PATTERNS> A space-separated list of glob patterns to exclude from the search [default: **/{node_modules,.git,target,dist,vendor}/**/*]
-C, --Command <COMMAND> The command to execute. Can be specified multiple times
-h, --help Print help
-V, --version Print version
```
### Basic Examples
**1. Fetch all Git repositories in the current directory.**
This will find every directory containing a `.git` subfolder and run `git fetch`
inside it.
```sh
Run --Pattern .git --Command "git fetch --all"
```
_This is the high-performance equivalent of:_
`find . -type d -name .git -execdir git fetch --all \;`
**2. Run multiple commands.**
Clean the `target` directory for all Rust projects.
```sh
Run --Pattern Cargo.toml --Command "cargo clean" --Command "echo Cleaned"
```
**3. Run `npm install` in all projects with a `package.json`.**
The default `--Exclude` rules will automatically prevent it from running inside
`node_modules`.
```sh
Run --Pattern package.json --Command "npm install"
```
### Advanced Options
- **`-R, --Root <DIRECTORY>`**: Start searching from a different directory.
```sh
Run --Root ~/projects --Pattern .git --Command "git status -s"
```
- **`-P, --Parallel`**: You can run things sequentially by omitting it if
sequential execution is preferred.
- **`-E, --Exclude <PATTERNS>`**: Override the default exclusion patterns. Note
that patterns are space-separated.
```sh
Run --Pattern .git -E "**/{node_modules,target,dist,build,cache}/**/*" -C "git status"
```
- **`-F, --File`**: Target files directly based on the pattern. This is less
common. For example, to run a linter on all TypeScript config files:
```sh
Run -F --Pattern "tsconfig.json" --Command "npx eslint tsconfig.json"
```
---
## Dependencies 🖇️
`Run` stands on the shoulders of giants. It is built with these excellent crates
from the Rust ecosystem:
- **[`clap`](https://crates.io/crates/clap)**: For robust and ergonomic
command-line argument parsing.
- **[`walkdir`](https://crates.io/crates/walkdir)**: For efficient,
cross-platform directory traversal.
- **[`globset`](https://crates.io/crates/globset)**: For high-performance file
path matching against glob patterns.
- **[`tokio`](https://crates.io/crates/tokio)**: The de-facto asynchronous
runtime for writing fast and reliable network and I/O-bound applications.
- **[`rayon`](https://crates.io/crates/rayon)**: A data-parallelism library that
makes it easy to convert sequential computations into parallel ones.
- **[`futures`](https://crates.io/crates/futures)**: Provides core abstractions
for asynchronous programming.
- **[`crossbeam-queue`](https://crates.io/crates/crossbeam-queue)**: For
high-performance, lock-free queues used in our concurrent pipeline.
- **[`once_cell`](https://crates.io/crates/once_cell)**: For safe, efficient,
and thread-safe one-time initialization of global state.
---
## License ⚖️
This project is released into the public domain under the **Creative Commons CC0
Universal** license. You are free to use, modify, distribute, and build upon
this work for any purpose, without any restrictions. For the full legal text,
see the [`LICENSE`](LICENSE) file.
---
## Changelog 📜
Stay updated with our progress! See [`CHANGELOG.md`](CHANGELOG.md) for a history
of changes specific to **Run**.