# cmprss
[](https://github.com/arcuru/cmprss/actions?query=workflow%3ANix)
[](https://crates.io/crates/cmprss)
[](https://codecov.io/gh/arcuru/cmprss)

**Mirrored on [GitHub](https://github.com/arcuru/cmprss) and [Codeberg](https://codeberg.org/arcuru/cmprss). GitHub is the official repo, but use either repo to contribute. Issues can't be synced so there may be some duplicates.**
A compression multi-tool for the command line.
Replace `tar` with something you can remember.
[Relevant XKCD](https://xkcd.com/1168/).
All compression libraries are statically compiled in, so no runtime dependencies required.
Currently supports:
- brotli
- bzip2
- gzip
- lz4
- lzma (legacy LZMA1)
- snappy (framed)
- tar
- xz
- zip
- zstd
## Install
Installation is available through source code and cargo. `cargo install cmprss` will install the latest version.
For Nix users, the repository contains a flake and an overlay. `nix run github:arcuru/cmprss`
A fully static musl-linked binary is also available for Linux: `nix build github:arcuru/cmprss#cmprss-static`
### Shell Completions
The Nix package installs Bash, Fish, and Zsh completions automatically.
For other installations, add the matching snippet to your shell profile. Supported shells: `bash`, `elvish`, `fish`, `powershell`, `zsh`.
Bash (`~/.bashrc`):
```bash
source <(cmprss completions bash)
```
Zsh (`~/.zshrc`):
```bash
source <(cmprss completions zsh)
```
Fish (`~/.config/fish/config.fish`):
```fish
## Usage
The primary goal is to infer behavior based on the input, so that you don't need to remember esoteric CLI arguments.
`cmprss` supports being very explicit about the inputs and outputs for scripting, but will also behave intelligently when you leave out info.
All commands read from left to right, input is always either piped from `stdin` or the first filename(s) specified, and output is either `stdout` or the last filename/directory.
The easiest way to understand is to look at some examples
Compress a file with gzip
```bash
cmprss file.txt file.txt.gz
```
Compress 2 files into a tar archive
```bash
cmprss file1.txt file2.txt archive.tar
```
Compress stdin with xz
```bash
Extract a tar archive to the current directory
```bash
cmprss archive.tar
```
Extract an xz compressed file
```bash
cmprss file.xz file.txt
```
Extract a gzip compressed file to stdout
```bash
cmprss file.txt.gz > file.txt
```
### Multi-level Compression
`cmprss` supports multi-level archives like `.tar.gz`, `.tar.xz`, or `.zstd.bz2` directly:
```bash
# Compress a directory to a tar.gz file
cmprss directory out.tar.gz
# Extract a tar.xz file to a directory
cmprss --extract archive.tar.xz output_dir
# Gzip an existing tar archive
cmprss archive.tar archive.tar.gz
# Extract just the xz layer
cmprss archive.tar.xz archive.tar
```
The common compound shortcut extensions also work and behave identically to their long forms:
| `.tgz` | `.tar.gz` |
| `.tbz`/`.tbz2` | `.tar.bz2` |
| `.txz` | `.tar.xz` |
| `.tzst` | `.tar.zst` |
You can also pass a compound format as the leading argument (like the `tar` subcommand) to make it explicit, without writing out a target filename:
```bash
# Compress a directory to directory.tar.gz
cmprss tar.gz directory
# Same, using the shortcut form
cmprss tgz directory out.tgz
```
Pipes can still be used if preferred:
```bash
### Examples of Explicit Behavior
All these examples will work with _any_ of the supported compression formats, provided that they support the input/output formats.
If output filenames are left out, `cmprss` will try to infer the filename based on the compression type.
Compress a file/directory to a `tar` archive:
```bash
cmprss tar filename # outputs to filename.tar
cmprss tar filename my_preferred_output_name.tar
```
Compress 2 files/directories into a `tar` archive:
```bash
cmprss tar dir_1/ dir_2/ combined.tar
cmprss tar file_1.txt file_2.txt # outputs to file_1.txt.tar
```
Extract a `tar` archive:
```bash
cmprss tar --extract archive.tar # extracts to the current directory
cmprss tar -e archive.tar custom_output_directory
```
Append new entries to an existing `tar` or `zip` archive:
```bash
cmprss tar --append new_file.txt archive.tar
cmprss zip -a new_file.txt extra_dir/ archive.zip
```
`--append` only works for container formats that can grow in place. Stream codecs (gzip, xz, …) and compound pipelines like `tar.gz` have no way to append without rewriting the whole archive, so they error instead of silently doing the wrong thing.
`cmprss` will detect if `stdin` or `stdout` is a pipe, and use those for I/O where it makes sense.
Create and extract a `tar.gz` archive with pipes:
```bash
# Or a full roundtrip in one line
## Contributing
### Development Environment
The primary supported developer environment is defined in the `flake.nix` file.
This is a [Nix Flake](https://nixos.wiki/wiki/Flakes) that pins versions of all packages used by `cmprss`.
It includes a `devShell` that can be used with [direnv](https://direnv.net/) to use the tools each time you enter the directory.
That being said, `cmprss` is a very standard Rust application and should work with recent Rust toolchains.
The CI runs on both a stable Rust toolchain and the pinned Nix versions to verify correctness of both.
If you run into any issues developing with either the Nix environment or a stable Rust environment, please open a Github issue with the details.
### Conventional Commits
Commits should conform to the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) standard.
A script to help create conforming commits is provided in `bin/commit.sh`, or via `task commit`.
### Test Coverage
PRs that improve the test coverage are encouraged.
Test coverage can be measured using `cargo llvm-cov report` and `cargo tarpaulin`.