Skip to main content

check-empty

#StandWithPalestine

A simple, dependency-free pre-commit / prek hook, CLI, library and GitHub Action conglomerate written in Python.

Makes sure selected files, even within directories, are empty according to as little filesystem stat calls as possible, and clears them effectively with minimal I/O if specified.

Prerequisites

Supports every Python 3.10 runtime. There are no other requirements.

Quickstart

If using double-asterisk globbing in the CLI, make sure it is enabled:

shopt -s globstar

similarly for extglob:

shopt -s extglob

Without installation (just trying out the capabilities):

uvx check-empty -Q src/mylib/py.typed docs/.nojekyll static/.gitkeep some_dir **/*.lock

Installation

# uv
uv tool install check-empty # bare executable on PATH
uv pip install check-empty # if you want to import check_empty for programmatic usage

pip install check-empty # pip

Show the help with:

check-empty --help # or check-empty -?

Usage

All the snippets below are equivalent, assuming globstar is on.

Run the CLI:

check-empty -Q src/mylib/py.typed docs/.nojekyll static/.gitkeep some_dir **/*.lock

In Python:

from check_empty import check
import glob

a = ['src/mylib/py.typed', 'docs/.nojekyll', 'static/.gitkeep', 'some_dir']
a.extend(glob.iglob('**/*.lock', recursive=True))
# build a list of paths to files or directories by manual globbing
check(a, verbosity=1)
# default verbosity is 2; in the command line, each -Q decreases it by 1 and
# each -V increases it by 1

As a pre-commit hook:

# .pre-commit-config.yaml
repos:
- repo: https://github.com/jonathandung/check-empty
  rev: v2.0.0 # repository version
  hooks:
    - id: check-empty # the hook
      args: # example list of arguments
        - -Q # flag to decrease output, applicable twice (shorthand for --quiet)
      files: ^src/mylib/py\.typed|docs/\.nojekyll|static/\.gitkeep|some_dir/.*|.*\.lock$
      # paths to files/directories to clear or keep empty as a single regular
      # expression (as per the somewhat restrictive pre-commit config schema),
      # relative to project root

equivalent in prek.toml format:

[[repos]]
repo = "https://github.com/jonathandung/check-empty"
rev = "v2.0.0"

[[repos.hooks]]
id = "check-empty"
args = ["-Q"]

[[repos.hooks.files]]
glob = [ # globset reference: https://docs.rs/globset/latest/globset/#syntax
  # this form is only supported by prek; see
  # https://prek.j178.dev/reference/configuration/?h=globs#files
  "src/mylib/py.typed",
  "docs/.nojekyll",
  "static/.gitkeep",
  "some_dir/**", # since directories cannot be passed directly, glob the files within
  "**/*.lock"
]

or (TOML 1.1+):

# using multiline inline tables
[[repos]]
repo = "https://github.com/jonathandung/check-empty"
rev = "v2.0.0"
hooks = [{
  id = "check-empty",
  args = ["-Q"],
  files = {
    glob = [
      "src/mylib/py.typed",
      "docs/.nojekyll",
      "static/.gitkeep",
      "some_dir/**",
      "**/*.lock"
    ]
  },
}]

As a GitHub Actions workflow step:

steps:
- uses: jonathandung/check-empty@v2.0.0 # the latest version on the GitHub Actions
  # marketplace; this step will fail and subsequent jobs will not run if any file is
  # not empty
  with:
    python-version: '3.14' # run the script on the latest stable Python version
    filenames: |
      src/mylib/py.typed
      docs/.nojekyll
      static/.gitkeep
      some_dir
    globs: '**/*.lock'
    # can also be an array of globs joined into a newline-delimited multiline string,
    # as in filenames

Also see the GitHub Action manifest, which contains the accepted action inputs, action outputs produced and their respective descriptions.

Notes

  1. If your file name starts with a hyphen, use a command of the form check-empty -- -this_is_actually_a_file.txt to avoid having the filename misinterpreted as a flag.
  2. Forward slashes can be used even on Windows, so there is no need to escape anything.
  3. Glob patterns are supported on *nix only. If on Windows, use a shell like Git Bash.
  4. To pass an argfile, use the @ prefix, and escape files whose names actually start with @ using the double-hyphen syntax.
  5. It may be unintuitive that a directory or archive being "empty" means all its files are empty, but this project explicitly targets files, since version control systems track files rather than directories.
  6. The program can recurse into some archives if specified, but it requires certain libraries to be installed to do so for certain formats. .7z (corresponding to the 7z extra) needs py7zr, .rar (the rar extra) needs rarfile, .lha / .lzh (the lzh extra) needs lhafile, .a / .ar / .lib (the ar extra) needs arpy, .ace (the ace extra) needs acefile. These may also slow down the checking significantly for large directories, since magic numbers must be read for every file and the I/O overhead accumulates. All the above extras are included in the all extra.
  7. Keep weird characters in your filenames to a minimum. They may become a problem in GitHub Actions usage.

Development

If you wish to contribute to this project, you are more than welcome. Please remember to read the AI use policy and the contributing guide.

To build the docs locally (needs Python 3.12+ because of Sphinx), install with the docs group using a package manager that supports it (e.g. pip 25.1+ or uv 0.4.27+), preferably into a virtual environment.

Tests are run with:

python -m test_check_empty

at the project root. pytest is not needed.

Release files for check-empty 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for check-empty 2.0.0
File Size Uploaded
check_empty-2.0.0.tar.gz 15.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for check-empty 2.0.0
File Interpreter ABI Platform
check_empty-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 35.1 kB

Release files / check_empty-2.0.0.tar.gz

Download URL check_empty-2.0.0.tar.gz
Size 15.7 kB
Tags Source
SHA-256 checksum
How to use checksums
9e5f970c5e6b969768952509190d19e2aea16b8970bf6d880a9ad221ed8ad00d
BLAKE2b-256 checksum
How to use checksums
1963238ede3659594bbcc7aa12db2b36e12ea5de31c6c9548fc2b7197e7d01bc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","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}

Release files / check_empty-2.0.0-py3-none-any.whl

Download URL check_empty-2.0.0-py3-none-any.whl
Size 19.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e5eaec6748d860f5746e47e2bde437c548fac20aa4ffac7a6e84ce05115d9b1f
BLAKE2b-256 checksum
How to use checksums
1ef9162e773062fba2646c7a28d3702562feb2ebf002cdf191590ed6e2816466
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","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}
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