Par is just like the GNU Parallel, but smaller.
  • Go 74.1%
  • Roff 17.7%
  • Nix 5.7%
  • Shell 1.4%
  • Makefile 1.1%
Find a file
2026-03-24 14:39:05 +03:00
parser fix(cmd_test): update to new edge-case for empty input parsing 2025-12-06 00:16:03 +03:00
scheduler scheduler: print to stderr 2026-03-24 14:39:05 +03:00
.editorconfig feat(editorconfig): add basic config. 2025-10-09 17:39:44 +03:00
.gitignore chore(gitignore): add main bin. 2025-10-08 15:56:43 +03:00
.treefmt.toml chore(treefmt): add a basic config file for go and nix. 2025-10-08 14:55:54 +03:00
completion.sh feat(complete): add shell completion script. 2025-10-10 10:23:29 +03:00
flake.lock chore(nix): add a basic shell flake for go. 2025-10-08 14:55:24 +03:00
flake.nix feat(man): add man.1 page. 2025-10-10 11:06:02 +03:00
go.mod feat(mod): init go module. 2025-10-08 15:02:09 +03:00
license refactor: rename readme and license files to be lowercase. 2025-10-08 14:56:36 +03:00
main.go fix(scheduler): break on error correctly 2025-11-25 16:19:26 +03:00
makefile fix(makefile): use rm -f on main bin. 2025-10-08 21:39:17 +03:00
man.1 doc: update -s flag to use the word "binaries" instead of "files" 2025-11-24 11:20:43 +03:00
readme.md doc: update -s flag to use the word "binaries" instead of "files" 2025-11-24 11:20:43 +03:00

Go Parallel (Par) is just like the GNU Parallel, but smaller 🤏

Simple Go binary with no external dependencies.

I created it mainly to practice Golang. Previously, I've used a simple bash script to do exactly that.

Description

Go Parallel, or short Par, is a CLI shell parallelisation tool. It allows you to apply various transformations to lines from stdin and run commands with them in parallel. This is very handy when you want to parallelise certain single-threaded tools.

Demo video

Usage

As it is just a smaller version of GNU Parallel, the usage is very simple.

This tool takes newline-separated INPUT, where CMD is called on each line.

<INPUT> | par [PARAMS] <CMD>

Examples

Transcode all PNG images to JXL

find . -type f -name '*.png' | par -J cjxl -e 9 {} {.}.jxl

Example above finds all the *.png files recursively, then runs cjxl on every file, placing new *.jxl files next to them. It runs the amount of cjxl instances equal to your CPU threads.

Rename all .tar.gz files to .tgz

find . -type f -name '*.tar.gz' | par -J mv {} {..}.tgz

Transcode all H264 videos to AV1, one at a time, and place in the current directory

find /mnt -type f -name '*.mp4' | par ffmpeg -i {} -c:a libopus -c:v libsvtav1 {//.}.mkv

Cli flags

You can always run par with no arguments to see all available flags.

Flag Description
-j Specify the number of parallel jobs to launch simultaniously. (default 1)
-J Use jobs equal to the number of available CPU threads.
-f Force command execution even if it contains no item consumers.
-s Load your default shell environment, aka $SHELL -c. Useful if you want to call shell functions instead of binaries.
-S Skip this number of inputs. Useful if you want to re-run on the same input and continue.
-e Stop processing and exit when any error occurs.
-E Force stderr printing even if there are multiple jobs (can get messy).
-d Remove the input file on successful processing.
-D Remove the input file always after processing.

Supported commands

Command Description
{} Paste the input as is.
{.} Removes the last file extension only.
{..} Removes all file extensions.
{/} Removes the file name from the path.
{//} Removes the directory path.
{//.} Removes the directory path and the last file extension.
{//..} Removes the directory path and all file extensions.

Examples

Command Description Input Result
{}.gz Paste the input as is, then append .gz to it. /foo.bar/file.tar /foo.bar/file.tar.gz
{.}.gz Remove the last extension only, then append .gz. /foo.bar/file.tar.xz /foo.bar/file.tar.gz
{..}.tgz Remove all file extensions, then append .tgz. /foo.bar/file.tar.gz /foo.bar/file.tgz
{/}/foo.txt Remove the file name from path, then append /foo.txt. /bar/file.tar.gz /bar/foo.txt
./foo/{//} Remove the directory path, then prepend ./foo/. /bar/file.tar.gz ./foo/file.tar.gz
./foo/{//.} Remove the directory path and the last extension, then prepend ./foo/. /bar/file.tar.gz ./foo/file.tar
./foo/{//..}.tgz Remove the directory path and all extensions, then prepend ./foo/. /bar/file.tar.gz ./foo/file

To-do

  • Shell completions.
  • Man pages.
  • Proper test coverage.
  • Extra commands, like {i} for index, {h} for file hash or {r} for random string.

Contribution

You can email me a patch to hi@voronind.com.

License

You can have all the funsies with my code. No responsibilities tho!

Please don't train text generators on it.