| 1 | #!/usr/bin/env bash |
| 2 | # Desc: Applies chmod to a segment of a directory branch of the |
| 3 | # filesystem tree. Changes applied to all directories starting with |
| 4 | # TIP and ending with (but not including) TRUNK. |
| 5 | |
| 6 | # Usage: chmoddirbr [path TRUNK] [path TIP] |
| 7 | # Input: arg1: TRUNK path |
| 8 | # arg2: TIP path |
| 9 | # arg3+ arguments to be passed on to chmod |
| 10 | # Output: None. |
| 11 | # Depends: GNU Coreutils 8.30 (chmod), Bash 5.0.3 |
| 12 | |
| 13 | # Example: chmoddirbr /tmp /tmp/1/2/3/4/5/6 o+rx |
| 14 | # This runs `chmod o+rx /tmp/1/2/3/4/5/6` |
| 15 | # `chmod o+rx /tmp/1/2/3/4/5` |
| 16 | # `chmod o+rx /tmp/1/2/3/4` |
| 17 | # ... |
| 18 | # `chmod o+rx /tmp/1` |
| 19 | |
| 20 | yell() { echo "$0: $*" >&2; } # print script path and all args to stderr |
| 21 | die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status |
| 22 | try() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails |
| 23 | main() { |
| 24 | declare -a chmod_args |
| 25 | declare -a dirs_branch |
| 26 | |
| 27 | arg1="$1"; shift; |
| 28 | arg2="$1"; shift; |
| 29 | chmod_args=("$@"); |
| 30 | |
| 31 | #yell "DEBUG:arg1:$arg1"; |
| 32 | #yell "DEBUG:arg2:$arg2"; |
| 33 | #yell "DEBUG:chmod_args:${chmod_args[@]}"; |
| 34 | |
| 35 | # Check input dirs |
| 36 | if [[ -d $arg1 ]]; then |
| 37 | dir_trunk="$(readlink -f "$arg1")"; # use full path |
| 38 | #yell "DEBUG:dir_trunk:$dir_trunk"; |
| 39 | else |
| 40 | die "ERROR:TRUNK is not a dir:$arg1"; |
| 41 | fi; |
| 42 | if [[ -d $arg2 ]]; then |
| 43 | dir_tip="$(readlink -f "$arg2")"; # use full path |
| 44 | #yell "DEBUG:dir_tip :$dir_tip"; |
| 45 | else |
| 46 | die "ERROR:TIP is not a dir:$arg2"; |
| 47 | fi; |
| 48 | |
| 49 | # Check if $dir_trunk points to $dir_tip |
| 50 | if [[ $dir_tip =~ ^"$dir_trunk" ]]; then |
| 51 | : |
| 52 | #yell "DEBUG:Tip is within trunk."; |
| 53 | else |
| 54 | yell "NOTE:dir_trunk:$dir_trunk"; |
| 55 | yell "NOTE:dir_tip :$dir_tip"; |
| 56 | die "ERROR:Tip is not within trunk."; |
| 57 | fi; |
| 58 | |
| 59 | # Assemble dirs_branch array |
| 60 | ## Note: dirs_branch will not include $dir_trunk |
| 61 | point="$dir_tip"; |
| 62 | while [[ $point != $dir_trunk ]]; do |
| 63 | #yell "DEBUG:start point :$point"; |
| 64 | #yell "DEBUG:start dir_trunk:$dir_trunk"; |
| 65 | dirs_branch+=("$point"); |
| 66 | |
| 67 | # Walk up branch |
| 68 | point="$(dirname "$point")"; |
| 69 | #yell "DEBUG:end point :$point"; |
| 70 | #yell "DEBUG:end dir_trunk:$dir_trunk"; |
| 71 | #yell ""; # debug |
| 72 | done; |
| 73 | unset point; |
| 74 | #yell "DEBUG:${dirs_branch[@]}"; |
| 75 | |
| 76 | # Perform action |
| 77 | n=0; |
| 78 | for dir in "${dirs_branch[@]}"; do |
| 79 | yell "STATUS:$((n+1)):Running: chmod $chmod_args $dir"; |
| 80 | try chmod "$chmod_args" "$dir" && ((n++)); |
| 81 | done; |
| 82 | yell "STATUS:Finished. Ran chmod $((n)) times."; |
| 83 | } # main program |
| 84 | |
| 85 | main "$@"; |
| 86 | |
| 87 | # Author: Steven Baltakatei Sandoval |
| 88 | # License: GPLv3+ |