Skip to main content

Recursively chmod directories, files, and executables with sensible defaults.

Project description

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

[!TIP] Files without an extension are inspected for a #! shebang line to decide whether they should be executable.

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

Project details


Download files

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

Source Distribution

pychmod-0.0.2.tar.gz (11.6 kB view details)

Uploaded Source

Built Distribution

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

pychmod-0.0.2-py3-none-any.whl (10.7 kB view details)

Uploaded Python 3

File details

Details for the file pychmod-0.0.2.tar.gz.

File metadata

  • Download URL: pychmod-0.0.2.tar.gz
  • Upload date:
  • Size: 11.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for pychmod-0.0.2.tar.gz
Algorithm Hash digest
SHA256 4d941d6e0ad8935b6064063e72114efa23f9ddd9b1aec7061fe911ebb69d3de5
MD5 c6a00a4bbecbf98847f1e6af9f3a6d19
BLAKE2b-256 9b4dab174e5fd4fc6f8e4722b078d613d8f92431d7121ae191541d56f370ba71

See more details on using hashes here.

File details

Details for the file pychmod-0.0.2-py3-none-any.whl.

File metadata

  • Download URL: pychmod-0.0.2-py3-none-any.whl
  • Upload date:
  • Size: 10.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for pychmod-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 3d4752305c600a8dff13428fcbaf0ef07d0c870407bacdb92bef3f543444f685
MD5 3c341893abf04904895c56d388a38a72
BLAKE2b-256 0be6059ac8c819c3ce2bb48f7f371dfdb30ac23ee903b85e72c971abb04dd772

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page