Skip to main content

OpenChmod

License: Apache 2.0 CI PyPI Python

Recursively fix file permissions across a project tree in one command.

pychmod walks a directory and applies sensible defaults — 0755 for directories, 0644 for regular files, 0755 for scripts and executables — so you don't have to chain find ... -exec chmod ... invocations or remember which mode goes where. Scripts are detected by extension or by #! shebang, even when there is no extension at all.

Features

  • One pass, three modes: separate permissions for directories, files, and executables.
  • Smart script detection: known extensions (.sh, .py, .pl, .rb, ...) plus shebang sniffing for extensionless files.
  • --dry-run to preview changes and --check to fail CI when permissions drift.
  • Glob-based --include / --exclude filters, repeatable.
  • Optional symlink following, off by default.
  • Zero runtime dependencies. Pure Python, 3.10+.

Why not just find -exec chmod?

The classic recipe needs three passes and assumes you know which files are scripts:

find . -type d -exec chmod 0755 {} +
find . -type f -exec chmod 0644 {} +
find . -type f \( -name "*.sh" -o -name "*.py" \) -exec chmod 0755 {} +

pychmod does the same in one walk, classifies scripts by shebang as well as extension (so an extensionless ./build with #!/usr/bin/env bash gets the right mode), and adds --dry-run plus --check so you can preview changes or fail CI on drift — none of which find gives you for free.

Installation

pip install pychmod

Quick start

Apply defaults (dirs=0755, files=0644, exec=0755) to a project tree:

pychmod /path/to/project

Preview without writing:

pychmod /path/to/project --dry-run

Verify in CI — exits non-zero if anything drifts:

pychmod /path/to/project --check

Usage

pychmod [-h] [-p DIR] [--dirperms DIRPERMS] [-f FILEPERMS] [-x EXECPERMS]
        [-e PATTERN] [-i PATTERN] [--files-only] [-s] [-v] [-n] [--check]
        [DIR]
Option Description Default
DIR / -p DIR Directory to traverse (positional or flag). —
--dirperms Octal mode for directories. 0755
-f, --fileperms Octal mode for regular files. 0644
-x, --execperms Octal mode for scripts/executables. 0755
-e, --exclude Glob pattern to exclude (repeatable). —
-i, --include Glob pattern to include, files only (repeatable). —
--files-only Skip directory permissions; only chmod files. false
-s, --symlinks Follow symlinks. false
-v, --verbose Print every entry processed. false
-n, --dry-run Show changes without applying them. false
--check Exit non-zero if any permissions are wrong. No changes made. false

Examples

Tighten down a webroot:

pychmod /var/www --dirperms 0750 --fileperms 0640 --execperms 0750

Skip VCS and cache directories:

pychmod /path/to/project -e .git -e __pycache__ --verbose

Only retouch Python and shell scripts:

pychmod /path/to/project -i "*.py" -i "*.sh"

Only fix C/C++ source files, leave directories untouched:

pychmod /path/to/project -i "*.c" -i "*.h" -i "*.cpp" --files-only

Follow symlinks (use with care):

pychmod /path/to/project --symlinks

Use as a pre-commit / CI gate

Add a --check step to your pipeline so a stray chmod 777 never lands on main:

- name: Verify file permissions
  run: pychmod . --check -e .git

Development

git clone https://github.com/Junbo-Zheng/OpenChmod.git
cd OpenChmod
pip install -e ".[dev]"
pytest

Release files for pychmod 0.0.2

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

Source distribution (sdist)

Source distribution for pychmod 0.0.2
File Size Uploaded
pychmod-0.0.2.tar.gz 11.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pychmod 0.0.2
File Interpreter ABI Platform
pychmod-0.0.2-py3-none-any.whl Python 3 none any Details

Total release size: 22.3 kB

Release files / pychmod-0.0.2.tar.gz

Download URL pychmod-0.0.2.tar.gz
Size 11.6 kB
Tags Source
SHA-256 checksum
How to use checksums
4d941d6e0ad8935b6064063e72114efa23f9ddd9b1aec7061fe911ebb69d3de5
BLAKE2b-256 checksum
How to use checksums
9b4dab174e5fd4fc6f8e4722b078d613d8f92431d7121ae191541d56f370ba71
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.12

Release files / pychmod-0.0.2-py3-none-any.whl

Download URL pychmod-0.0.2-py3-none-any.whl
Size 10.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3d4752305c600a8dff13428fcbaf0ef07d0c870407bacdb92bef3f543444f685
BLAKE2b-256 checksum
How to use checksums
0be6059ac8c819c3ce2bb48f7f371dfdb30ac23ee903b85e72c971abb04dd772
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.12

Release history Release notifications | RSS feed

This release

0.0.2 This release

2 release 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