Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 104 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,18 @@

## Overview

This Bash script interactively checks specific file or directory permissions (Owner, Group, or Other; Read, Write, or Execute) for a list of paths provided in an input file. It provides clear, color-coded output indicating whether the specified permission is set for each path.
This Bash script checks specific file or directory permissions (Owner, Group, or Other; Read, Write, or Execute) for a list of paths provided in an input file. It provides clear, color-coded output indicating whether the specified permission is set for each path.

It greets you with a big title banner and a short description, then runs either
**interactively** — prompting for the input file and the permission to check —
or **non-interactively** via command-line flags, which makes it easy to drop
into scripts and CI. When any required value is omitted and a terminal is
attached, the script prompts for it; when nothing is attached (a pipe or CI
job), it fails fast with a clear message instead of hanging.

<p align="center">
<img src="assets/dirPathPerms_appThumbnail.png" alt="dirPathPerms banner and permission-check output" width="800">
</p>

## Use Case

Expand All @@ -23,27 +34,38 @@ This script is useful for:

## Features

* **Title banner:** prints a big ASCII title and a one-line description each run.
* **Two run modes:** fully interactive prompts, or non-interactive with flags
(`--file`, `--who`, `--perm`) for scripting and CI.
* Checks permissions for files and directories listed in a specified input file.
* Allows checking for Owner (`u`), Group (`g`), or Other (`o`) permissions.
* Allows checking for Owner (`u`), Group (`g`), or Other (`o`) permissions, or
**all three at once** with `--all` (a compact permission matrix).
* Allows checking for Read (`r`), Write (`w`), or Execute (`x`) permissions.
* Interactive prompts guide the user to select the input file and the desired permission check.
* Input validation for file existence and permission choices.
* Interactive prompts guide the user to select the input file and the desired
permission check, and validate every choice.
* Clear, color-coded output:
* **Green (`YES`)**: The specified permission is set.
* **Red (`NO`)**: The specified permission is **not** set.
* Displays the full permission string (e.g., `Owner: rwx, Group: r-x, Other: r--`) for context in the output.
* A **summary line** at the end with granted / denied / skipped counts.
* Displays the full permission string (e.g., `owner rwx | group r-x | other r--`)
for context in the output.
* **Comment & blank-line support:** lines in the input file that are empty or
start with `#` are skipped.
* Gracefully handles and reports paths listed in the input file that do not exist.
* Nicely formats long prompt text using line wrapping.
* **Cross-platform:** works with both GNU (`stat -c`) and BSD/macOS (`stat -f`)
`stat`, so no GNU coreutils install is required on macOS.
* Color is disabled automatically when output is piped or redirected, and can be
turned off explicitly with `--no-color` (or the `NO_COLOR` environment variable).
* `--help` and `--version` flags.

## Prerequisites

* A Bash-compatible shell (standard on most Linux distributions and macOS).
* Standard Unix/Linux command-line utilities, specifically:
* GNU `stat` (used for retrieving file status, including permissions). The
script calls `stat -c '%A'`, which is GNU coreutils syntax — standard on
Linux. On macOS/BSD, install GNU coreutils and make sure its `stat` comes
first on your `PATH` (for Homebrew, the `gnubin` directory).
* `read`, `echo`, `printf` (standard shell built-ins).
* `stat` for retrieving file permissions. The script auto-detects GNU
(`stat -c '%A'`) and BSD/macOS (`stat -f '%Sp'`) variants, so it works on
Linux and macOS out of the box — no GNU coreutils install required.
* `read`, `printf`, `tr` (standard shell built-ins / utilities).

## Installation

Expand All @@ -55,33 +77,71 @@ This script is useful for:

## How to Run

1. Create an input file containing the list of absolute paths you want to check (see [Input File Format](#input-file-format) below).
2. Open your terminal.
3. Navigate to the directory where you saved `dirPathPerms.sh`.
4. Execute the script:
```bash
./dirPathPerms.sh
```
5. Follow the interactive prompts:
* Enter the path to your input file when prompted.
* Choose whether to check permissions for Owner (`O`), Group (`G`), or Other (`E`).
* Choose whether to check for Read (`R`), Write (`W`), or Execute (`X`) permission.
Create an input file containing the list of absolute paths you want to check
(see [Input File Format](#input-file-format) below), then run the script in
whichever mode suits you.

### Interactive

```bash
./dirPathPerms.sh
```

The script will then process each path in your input file and print the results to the console.
Follow the prompts:

* Enter the path to your input file when prompted.
* Choose whether to check permissions for Owner (`O`), Group (`G`), Other (`E`),
or All (`A`).
* Choose whether to check for Read (`R`), Write (`W`), or Execute (`X`) permission.

The script processes each path and prints the results to the console.

### Non-interactive

Supply the values as flags and the script runs without prompting — ideal for
scripts, cron jobs, and CI:

```bash
# Does the group have write access to every listed path?
./dirPathPerms.sh --file paths.txt --who group --perm write

# Show read access for owner/group/other across all paths, colors off
./dirPathPerms.sh --all --perm read --file paths.txt --no-color

# The file can also be passed positionally
./dirPathPerms.sh -w owner -p x paths.txt
```

If some (but not all) values are provided, the script prompts for the rest when
a terminal is attached, or exits with a helpful error when one is not.

### Command-line options

| Option | Description |
|---|---|
| `-f`, `--file FILE` | Input file: one absolute path per line. Blank lines and `#` comments are ignored. |
| `-w`, `--who WHO` | Whose permission to check: `owner`\|`group`\|`other` (aliases `u`\|`g`\|`o`). |
| `-p`, `--perm PERM` | Permission to check: `read`\|`write`\|`execute` (aliases `r`\|`w`\|`x`). |
| `-a`, `--all` | Check owner, group **and** other at once (permission matrix). |
| `--no-color` | Disable colored output (also honors the `NO_COLOR` env var). |
| `-h`, `--help` | Show help and exit. |
| `-V`, `--version` | Print the version and exit. |

## Input File Format

The input file should be a plain text file where **each line contains exactly one absolute path** to a file or directory.

* **Absolute paths are required** to ensure the script can find the files/directories regardless of where the script itself is executed from.
* Lines starting with `#` could be used for comments if you modify the script to ignore them, but the current version treats every line as a potential path.
* **Blank lines and lines starting with `#` are ignored**, so you can annotate and space out the file freely.

**Example Input File (`myPaths.txt`):**

```text
# system files
/etc/passwd
/home/user/important_script.sh
/var/log/app.log

/tmp
/non/existent/path
/data/shared_folder
Expand All @@ -100,58 +160,39 @@ Let's say you want to check if members of the owning **Group** have **Write** ac
* `/non/existent/path` : Does not exist
* `/data/shared_folder` : `drwxrwx---` (Owner: rwx, Group: rwx, Other: ---)

### Running the Script
### Running the Script (non-interactive)

```bash
./dirPathPerms.sh
```

### Interaction

```text
Example file format (one absolute path per line):

/location/of/dirname1
/location/of/dirname2
/location/of/filename1
/location/of/filename2

Enter the name of the file containing the directories or files we should check.
Absolute paths are required if the script is executed from a different
location.

File path: my_paths.txt # <-- User enters the file path

Check permissions for (O)wner, (G)roup, Oth(e)r?

Choice: G # <-- User enters 'G' for Group

Check for (R)ead, (W)rite, or e(X)ecute permissions?

Permission: W # <-- User enters 'W' for Write
./dirPathPerms.sh --file myPaths.txt --who group --perm write
```

### Expected Output

```text
Checking write permission for Group — from myPaths.txt

# (Output color formatting shown conceptually with Markdown)
# **Green Text** for YES, *Red Text* for NO
/etc/passwd NO (no write for Group) [owner rw- | group r-- | other r--]
/home/user/important_script.sh NO (no write for Group) [owner rwx | group r-x | other ---]
/var/log/app.log YES [owner rw- | group rw- | other ---]
/tmp YES [owner rwx | group rwx | other rwt]
/non/existent/path SKIP (path does not exist)
/data/shared_folder YES [owner rwx | group rwx | other ---]

**/etc/passwd *NO write permission for Group (Owner: rw-, Group: r--, Other: r--)*
**/home/user/important_script.sh *NO write permission for Group (Owner: rwx, Group: r-x, Other: ---)*
**/var/log/app.log **YES (Owner: rw-, Group: rw-, Other: ---)**
**/tmp **YES (Owner: rwx, Group: rwx, Other: rwt)**
Skipping: /non/existent/path (Not a file or directory)
**/data/shared_folder **YES (Owner: rwx, Group: rwx, Other: ---)**
Summary: 3 granted, 2 denied, 1 skipped (5 checked).
```

`YES` lines are green, `NO` lines red, and `SKIP` lines yellow (colors are
omitted when output is piped or `--no-color` is set). With `--all`, each path
instead shows a per-class matrix, e.g. `u+ g- o-` for a permission present for
the owner but not the group or other.

## Output Explanation

* `YES` (Green Text): Indicates that the requested permission (`write` in the example) is set for the specified entity (`Group` in the example) on that file or directory.
* `NO` (Red Text): Indicates that the requested permission is not set for the specified entity. The message clarifies which permission (`write`) and entity (`Group`) were checked.
* (Owner: ..., Group: ..., Other: ...): Appears on both `YES` and `NO` lines, showing the actual permission breakdown (`rwx` format) for Owner, Group, and Other for context.
* `Skipping: ... (Not a file or directory)`: This message is printed when a path listed in the input file does not exist on the filesystem.
* `YES` (Green): The requested permission (`write` in the example) is set for the specified entity (`Group` in the example) on that path.
* `NO` (Red): The requested permission is not set for the specified entity. The message clarifies which permission and entity were checked.
* `[owner ... | group ... | other ...]`: Appears on both `YES` and `NO` lines, showing the actual permission breakdown (`rwx` format) for context.
* `SKIP ...` (Yellow): Printed when a path listed in the input file does not exist or its mode can't be read.
* `Summary`: A final tally of granted / denied / skipped paths.

## License

Expand Down
Binary file added assets/dirPathPerms_appThumbnail.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading