Skip to main content

beautify_bash

CI PyPI

A code formatter / beautifier for bash and zsh shell scripts.

Originally written in Ruby, then Python, by Paul Lutus; revived here with a proper package layout, a Typer CLI, uv tooling, a test suite, and support for shell dialects.

Install

uv tool install beautify-bash      # as a standalone command
uv add beautify-bash               # as a project dependency
pipx install beautify-bash         # or with pipx

Run it without installing:

uvx beautify-bash script.sh

Requires Python 3.9 or newer (tested through 3.14).

Use

Like shfmt and gofmt, it prints to standard output and changes nothing on disk unless you ask it to:

beautify-bash script.sh                 # print the formatted script
beautify-bash -w script.sh              # rewrite in place, keeping script.sh~
beautify-bash -w --no-backup script.sh  # rewrite without a backup
beautify-bash -o tidy.sh script.sh      # write the result to another file
beautify-bash --check src/*.sh          # exit 1 if anything would change (CI)
beautify-bash --diff script.sh          # show a unified diff, write nothing
beautify-bash --indent 4 script.sh      # four spaces per level
beautify-bash --tabs script.sh          # indent with tabs
beautify-bash -d zsh script.zsh         # force a dialect
cat script.sh | beautify-bash -         # stdin to stdout
beautify-bash -w src/*.sh               # format a whole directory
python -m beautify_bash script.sh       # same thing via the module

Standard output carries only the formatted script; progress notes, diffs of the --check kind, and errors go to standard error, so beautify-bash x.sh > y.sh is safe.

Options

Option Meaning
(none) Print the formatted script to stdout; several inputs are concatenated.
-w, --write Rewrite each input file in place.
-o, --output PATH Write the result to PATH (- means stdout).
-i, --indent N Spaces per indentation level (default 2).
--tabs / --spaces Indent with tab characters instead of spaces.
-d, --dialect auto (default), bash, or zsh.
--check Write nothing; exit 1 if a file would change.
--diff Print a unified diff instead of writing.
--backup / --no-backup With -w, keep the original as FILE~ (default on).
-q, --quiet Suppress per-file progress notes.
-V, --version Print the version and exit.

-w, -o, --check and --diff are mutually exclusive, and -w cannot rewrite standard input.

Exit codes: 0 clean, 1 a file changed (under --check/--diff) or a syntax problem was reported, 2 a file could not be read or written, or the options conflict.

Dialects

--dialect auto picks the dialect from the shebang line first, then the file name (.zsh, .zshrc, .zshenv, …), and falls back to bash.

Dialect Block keywords
bash case/esac, if/then/elif/else/fi, do/done, {}, (), []
zsh everything bash has, plus foreach … end and } always {

Adding a shell means adding one Dialect instance in dialects.py — the indenter itself is dialect agnostic.

Library use

from beautify_bash import ZSH, Beautifier, beautify_string

result = beautify_string(open("script.sh").read())
print(result.text)
print(result.dialect.name, result.ok, result.errors)

# Explicit configuration
tidy = Beautifier(indent_char="\t", indent_size=1, dialect=ZSH)
print(tidy.format("foreach f (a b)\nprint $f\nend").text)

The 1.x API (BeautifyBash, beautify_string(data, path) -> (text, error), beautify_file, tab_str, tab_size) still works.

What is preserved verbatim

Re-indenting must never change what a script does, so these regions are passed through byte for byte:

  • here-document bodies (<<EOF, and <<-EOF with its indented terminator),
  • lines inside a multi-line '…' or "…" string,
  • everything inside comments and quotes is ignored for keyword counting.

Shell reserved words only count as keywords in command position — at the start of a line or after ;, &, |, or a bracket — so echo done no longer dedents the following lines.

Pre-commit

repos:
  - repo: local
    hooks:
      - id: beautify-bash
        name: beautify-bash
        entry: beautify-bash -w
        language: system
        types: [shell]

Development

uv sync                     # create .venv and install dev dependencies
uv run pytest               # run the tests
uv run pytest --cov         # with coverage
uv run ruff check .         # lint
uv run ruff format .        # format the Python sources
uv run mypy                 # type check

The test suite is in tests/:

Roadmap

See TODO.md.

License

GPL-2.0-or-later. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

beautify_bash-2.0.0.tar.gz (92.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

beautify_bash-2.0.0-py3-none-any.whl (20.7 kB view details)

Uploaded Python 3

File details

Details for the file beautify_bash-2.0.0.tar.gz.

File metadata

  • Download URL: beautify_bash-2.0.0.tar.gz
  • Upload date:
  • Size: 92.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for beautify_bash-2.0.0.tar.gz
Algorithm Hash digest
SHA256 d9eaef33f8c7a967fc52ce90aaf235b84b5df3049db579c64ef3f0ffe670d0a9
MD5 f889779193f2bfe8d150f577764748fb
BLAKE2b-256 e4e5caef231235646d08a4d47622ba7d73b1736247bc250fbca4dcbc1e0c1d61

See more details on using hashes here.

File details

Details for the file beautify_bash-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: beautify_bash-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 20.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for beautify_bash-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 db64a72d645226a220cfd84b52f6baa1bd4fb63f00af7c04d4822f46e8b3d385
MD5 6f5a7951dd2e1b3ad0d4126a10317ea4
BLAKE2b-256 d9dec7ff8b3977481bd7b7cd656b24856a54162fa772f7dcb26aa537c63c8f58

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

2.0.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page