Skip to content

feat(gemini): A whimsical Bash script to find and optionally clean up old, unused files and empty directories, metaphorically sweeping away 'digital dust bunnies'.#5125

Open
polsala wants to merge 1 commit into
mainfrom
ai/gemini-20260707-0736
Open

feat(gemini): A whimsical Bash script to find and optionally clean up old, unused files and empty directories, metaphorically sweeping away 'digital dust bunnies'.#5125
polsala wants to merge 1 commit into
mainfrom
ai/gemini-20260707-0736

Conversation

@polsala

@polsala polsala commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Implementation Summary

  • Utility: nightly-digital-dust-bunny-sweeper
  • Provider: gemini
  • Location: bash-utils/nightly-nightly-digital-dust-bunny-s-8
  • Files Created: 3
  • Description: A whimsical Bash script to find and optionally clean up old, unused files and empty directories, metaphorically sweeping away 'digital dust bunnies'.

Rationale

  • Automated proposal from the Gemini generator delivering a fresh community utility.
  • This utility was generated using the gemini AI provider.

Why safe to merge

  • Utility is isolated to bash-utils/nightly-nightly-digital-dust-bunny-s-8.
  • README + tests ship together (see folder contents).
  • No secrets or credentials touched.
  • All changes are additive and self-contained.

Test Plan

  • Follow the instructions in the generated README at bash-utils/nightly-nightly-digital-dust-bunny-s-8/README.md
  • Run tests located in bash-utils/nightly-nightly-digital-dust-bunny-s-8/tests/

Links

  • Generated docs and examples committed alongside this change.

Mock Justification

  • Not applicable; generator did not introduce new mocks.

… old, unused files and empty directories, metaphorically sweeping away 'digital dust bunnies'.
@polsala

polsala commented Jul 7, 2026

Copy link
Copy Markdown
Owner Author

🤖 Review by GROQ Agent

✅ What's solid

  • Self‑contained utility – the script lives in its own folder with a README and tests, so it won’t interfere with other parts of the repo.
  • User‑friendly interface – clear usage message, dry‑run flag, and an interactive confirmation step make it safe for casual use.
  • Robust file handlingfind … -print0 together with xargs -0 correctly deals with filenames that contain spaces or newlines.
  • Good test harness – the test suite creates an isolated temporary directory, sets explicit modification times, and validates both dry‑run and real‑run paths.
  • Whimsical documentation – the README is pleasant to read and explains the feature set, installation, and examples concisely.

🧪 Tests

Strengths

  • Covers the two main execution paths (dry‑run and actual deletion).
  • Verifies that only the expected old files/empty dirs are targeted and that newer files and non‑empty directories survive.

Opportunities for improvement

  • Edge‑case coverage – add tests for:
    • Invalid arguments (missing directory, non‑numeric age, unknown flag).
    • Non‑existent target directory (should exit with an error).
    • Negative confirmation (n or empty input) to ensure the script aborts without deleting anything.
    • A scenario where no dust bunnies are found (the “sparkling clean” message).
  • Spaces & special characters – create a file like "$TEST_DIR/old file with spaces.txt" and ensure it appears in the dry‑run output and is deleted correctly.
  • Symlink handling – add a symlink pointing to an old file and confirm the script does not follow it unintentionally (or document the intended behaviour).
  • Exit‑code assertions – capture $? after each run and assert that the script returns 0 on success and non‑zero on error conditions.

Example snippet for a space‑handling test:

touch -d "31 days ago" "$TEST_DIR/old file with spaces.txt"
OUTPUT=$("$SCRIPT_PATH" "$TEST_DIR" 30 --dry-run)
grep -q "old file with spaces.txt" <<<"$OUTPUT" || { echo "Missing spaced file"; exit 1; }

🔒 Security

  • Potential symlink racerm -v will follow symlinks. If an attacker can place a symlink inside the target directory that points outside the tree, the script could delete arbitrary files.
    • Mitigation: Use rm -v --preserve-root --no-dereference (or -P on GNU rm) or add a check that the path is inside $TARGET_DIR before deletion.
  • Lack of strict Bash options – the script runs without set -euo pipefail, which means:
    • Unset variables could expand to empty strings silently.
    • Errors in pipelines (e.g., a failing find) are ignored.
    • Adding set -euo pipefail at the top would make failures abort early and avoid unintended side‑effects.
  • Shebang portability#!/bin/bash assumes Bash is located at /bin/bash. Using #!/usr/bin/env bash is more portable across environments (e.g., macOS, Alpine).

Quick fix example:

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'   # safe field splitting

🧩 Docs / Developer Experience

  • README enhancements
    • Document required Bash version (≥ 4 for associative arrays, though not used here) and any external dependencies (find, xargs, rm, rmdir).
    • Explain the meaning of the exit codes (e.g., 0 = success, 1 = usage error, 2 = target not found).
    • Add a “Troubleshooting” section for common pitfalls (e.g., permission errors, running on a read‑only filesystem).
  • Usage examples – include a short example that pipes the script into less for a quick glance, or shows how to integrate it into a cron job.
  • Contribution guidelines – the README mentions “Feel free to suggest new whimsical messages”, but linking to a CONTRIBUTING.md would give contributors a concrete place to open PRs.

🧱 Mocks / Fakes

  • The test suite already uses a temporary directory as a sandbox, which is the right approach for Bash utilities that touch the filesystem.
  • No external services are involved, so no additional mocks are needed.
  • Consider wrapping destructive commands (rm, rmdir) in functions that can be overridden in tests (e.g., delete_file() { rm -v "$@"; }). This would let you verify the exact command line invoked without actually deleting files, making the tests faster and safer when run in CI environments that may have stricter permissions.

Illustrative pattern:

# In dust_bunny_sweeper.sh
delete_file() { rm -v "$@"; }
delete_dir()  { rmdir -v "$@"; }

# In tests (source the script then override)
source "$SCRIPT_PATH"
delete_file() { echo "MOCK rm $*"; }
delete_dir()  { echo "MOCK rmdir $*"; }

Summary of actionable items

  • Add set -euo pipefail and switch to #!/usr/bin/env bash.
  • Harden deletion against symlink attacks (e.g., rm -P or path validation).
  • Expand test coverage to include invalid arguments, empty results, spaces/special characters, symlinks, and exit‑code checks.
  • Enrich the README with version/dependency info, exit‑code semantics, and a troubleshooting section.
  • (Optional) Abstract destructive commands into overridable functions to enable pure‑mock testing.

These tweaks will make the utility more robust, secure, and easier for future contributors to understand and extend. 🚀

@polsala

polsala commented Jul 7, 2026

Copy link
Copy Markdown
Owner Author

🤖 Review by GROQ Agent

✅ What's solid

  • Self‑contained utility – the script, its README, and tests live in a dedicated folder, so they won’t interfere with the rest of the repo.
  • User‑friendly interface – clear usage message, a --dry‑run flag, and an interactive confirmation step make the tool safe for casual users.
  • Robust file handling – using find … -print0 together with xargs -0 correctly handles filenames that contain spaces, newlines or other special characters.
  • Graceful no‑op handling – when nothing matches, the script exits with a friendly “sparkling clean” message and a zero status.
  • Comprehensive test suite – the tests spin up a temporary directory, set precise modification times, and verify both dry‑run and actual‑deletion paths.

🧪 Tests

  • Positive coverage – the current tests exercise the main happy‑path scenarios (old files, empty dirs, dry‑run, interactive deletion).
  • Edge‑case suggestions
    • Add a test for filenames containing spaces or newlines to confirm the -print0 / xargs -0 pipeline works as expected.
    • Verify the script fails gracefully when the target directory does not exist or is not readable (e.g., chmod 000).
    • Include a test that supplies an unknown flag (e.g., --foo) and checks that the script exits with a non‑zero status and prints the usage.
    • Test the non‑interactive mode (e.g., piping n or using yes/no automatically) to ensure the script aborts without deleting anything.
    • Consider a large‑scale test (hundreds of files) to ensure the xargs invocation does not hit argument‑length limits.

Sample test snippet for spaces in filenames:

# inside the temporary test dir
touch -d "31 days ago" "$TEST_DIR/'file with spaces.txt'"
OUTPUT=$("$SCRIPT_PATH" "$TEST_DIR" 30 --dry-run)
grep -q "file with spaces.txt" <<<"$OUTPUT" && echo "Space‑filename test PASSED"
  • Testing framework – while a plain Bash script works, adopting a lightweight framework like BATS would give you built‑in assertions, better output formatting, and easier test discovery.

🔒 Security

  • Symlink safetyfind will follow symlinks by default when -type f is used. Consider adding -P (no dereference) or explicitly excluding symlinks (! -type l) to avoid unintentionally deleting files outside the target tree.

  • Permission checks – the script runs rm -v and rmdir -v without verifying that the current user has the necessary permissions. Adding a pre‑flight check (e.g., test -w "$TARGET_DIR" or handling rm errors) will produce clearer error messages instead of a silent failure.

  • Shell options – enable stricter Bash settings at the top of the script:

    set -euo pipefail
    IFS=$'\n\t'

    This prevents accidental use of undefined variables and propagates errors from pipelines.

  • Input sanitisation – the script already quotes variables, but be mindful of any future expansions that might use eval or command substitution with untrusted input.

🧩 Docs/DX

  • Usage section – the README explains the basic invocation, but adding a --help flag (e.g., if [[ "$1" == "--help" ]]; then ...) would let users view the usage without triggering an error.
  • Exit codes – document the meaning of the script’s exit statuses (e.g., 0 = success, 1 = usage error, 2 = runtime error).
  • Prerequisites – note the required Bash version (≥ 4 for associative arrays, if you ever add them) and that the script depends only on core utilities (find, xargs, rm, rmdir).
  • Dry‑run output example – include a short snippet of what a dry‑run looks like; this helps users verify they’re targeting the right files before committing to deletion.
  • Internationalisation – the whimsical messages are hard‑coded English strings. If the repo ever targets a broader audience, consider extracting them to variables or a separate messages file.

🧱 Mocks/Fakes

  • Current approach – the tests create a real temporary directory on the host filesystem, which is a solid, low‑dependency strategy for Bash scripts.
  • Potential enhancements
    • Use trap to capture and assert on the exact rm/rmdir commands that would be executed (e.g., by temporarily overriding rm and rmdir with wrapper functions that log calls). This can give you finer‑grained verification without actually deleting files.
    • If you adopt BATS, you can leverage its setup/teardown hooks to automatically create and clean the temporary environment, reducing boilerplate.

Overall, the utility is well‑structured, the tests are functional, and the documentation is pleasant. Addressing the security hardening points and expanding test coverage will make the script more robust and production‑ready.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant