#!/usr/bin/env bash set -euo pipefail usage() { echo "Usage: $(basename "$0") [options] TARGET" echo "" echo "Commands:" echo " add Add/update path comment in first 5 lines of each file" echo " undo Remove any path comment from first 5 lines of each file" echo "" echo "Options:" echo " -c Comment symbol (e.g., '#' or '//') [required for add]" echo " -e Exclude pattern (can be specified multiple times)" exit 1 } [[ $# -lt 1 ]] && usage cmd="$1" shift [[ "$cmd" != "add" && "$cmd" != "undo" ]] && usage comment_sym="" excludes=() while getopts "c:e:h" opt; do case $opt in c) comment_sym="$OPTARG" ;; e) excludes+=("$OPTARG") ;; h) usage ;; *) usage ;; esac done shift $((OPTIND - 1)) [[ $# -ne 1 ]] && usage if [[ "$cmd" == "add" ]]; then [[ -z "$comment_sym" ]] && { echo "Error: -c is required for add" >&2 usage } fi target="$(realpath "$1")" base_dir="$(pwd)" strip_path_comment() { local file="$1" awk 'NR <= 5 && /path: / { next } { print }' "$file" >"$file.tmp" mv "$file.tmp" "$file" } process_file() { local file="$1" # shellcheck disable=SC2295 local rel_path="${file#$base_dir/}" local path_comment="$comment_sym path: $rel_path" strip_path_comment "$file" local line1 IFS= read -r line1 <"$file" 2>/dev/null || line1="" if [[ "$line1" =~ ^#! ]]; then { echo "$line1" echo "$path_comment" tail -n +2 "$file" } >"$file.tmp" else { echo "$path_comment" cat "$file" } >"$file.tmp" fi mv "$file.tmp" "$file" } dispatch() { local file="$1" if [[ "$cmd" == "add" ]]; then process_file "$file" else strip_path_comment "$file" fi } if [[ -f "$target" ]]; then dispatch "$target" elif [[ -d "$target" ]]; then find_cmd=(find "$target" \( -name ".*" -prune \)) if [[ ${#excludes[@]} -gt 0 ]]; then find_cmd+=(-o \() for i in "${!excludes[@]}"; do [[ $i -gt 0 ]] && find_cmd+=(-o) find_cmd+=(-path "*/${excludes[$i]}" -prune) find_cmd+=(-o -path "*/${excludes[$i]}/*" -prune) done find_cmd+=(\)) fi find_cmd+=(-o -type f -print0) while IFS= read -r -d '' file; do dispatch "$file" done < <("${find_cmd[@]}") else echo "Error: $target is not a file or directory" >&2 exit 1 fi