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.
Supports every Python 3.10 runtime. There are no other requirements unless you want to check if files in certain types of (compressed) archives are empty.
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
# 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 -?
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: v3.0.1 # 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 = "v3.0.1"
[[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 = "v3.0.1"
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@v3.0.1 # 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.
check-empty -- -this_is_actually_a_file.txt to avoid having the filename
misinterpreted as a flag.@ prefix, and escape files whose names actually start with @ using the
double-hyphen syntax.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.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.