#!/usr/bin/env sh # compat: +ash +bash +dash +hush +ksh +mksh +oksh +osh +posh +yash +zsh __permit_hex() { if xxd -l 0 2>/dev/null; then __permit_hex() { exec xxd -p -l4 -- "$@"; } else __permit_hex() { exec hexdump -ve '1 1 "%02x"' -n4 -- "$@"; } fi __permit_hex "$@" } permit() { ### @- conditionally set executable permissions on each of its arguments. ### flags: ### * `-a` -- automatic: skip any files whose contents do not begin with ### with one of several signatures. this does not affect directories. ### * `-m` -- manual: turn off automatic mode. (default) ### * `-e` -- everything: consider both regular files and directories. (default) ### * `-f` -- files: skip any arguments that are not regular files. ### * `-d` -- directories: skip any arguments that are not directories. ### * `-n` -- dry-run: don't actually change anything. ### * `-v` -- verbose: print changes before doing them. ### ### the `-e`, `-f`, and `-d` flags all override one another, and any of them ### can be combined with `-a`. arguments that are neither regular files nor ### directories (such as symlinks) are always skipped. arguments that are ### already executable by the current user are skipped. arguments that do ### not appear to refer to an existing file are passed through to chmod. ### directories are never recursed. unset __permit_4 __permit_a __permit_f __permit_h __permit_m __permit_n __permit_v __permit_x || return __permit_h="[-v] [-n] [-a | -m] [-e | -f | -d] [--] {files...}" if [ $# = 0 ]; then printf >&2 'usage: permit %s\n' "$__permit_h" return 64; fi __permit_v=0 # verbosity __permit_n=0 # dry-run __permit_m=e # mode __permit_a=0 # automatic unset __permit_stop || return for __permit_f; do shift case "${__permit_stop+:}$__permit_f" in (/\?|-h|-help|--help) printf 'usage: permit %s\n' "$__permit_h" return 0;; (--) __permit_stop=1;; (-?*) while __permit_f="${__permit_f#?}"; [ -n "$__permit_f" ]; do case "${__permit_f}" in (v*) __permit_v=1;; # verbosity (n*) __permit_n=1;; # dry-run (a*) __permit_a=1;; # automatic (m*) __permit_a=0;; # manual (e*) __permit_m=e;; # everything (f*) __permit_m=f;; # files only (d*) __permit_m=d;; # directories only (*) printf >&2 'permit: unknown flag: -%.1s\n' "$__permit_f" return 64;; esac done;; (*) set -- "$@" "$__permit_f";; esac done if [ $# = 0 ]; then printf >&2 'usage: permit %s\n' "$__permit_h" return 64; fi __permit_x= for __permit_f; do [ -n "$__permit_x" ] || { __permit_x=0; set --; } if [ -x "$__permit_f" ]; then : # pass elif ! [ -e "$__permit_f" ]; then set -- "$@" "$__permit_f" elif [ "$__permit_a" = 1 ] && ! [ -d "$__permit_f" ]; then __permit_4="$(__permit_hex "$__permit_f")" || __permit=$? case "$__permit_4" in (7f454c46) false;; (2321*) false;; (4d5a*) false;; esac || set -- "$@" "$__permit_f" # runs when a case matches elif [ "-$__permit_m" "$__permit_f" ]; then set -- "$@" "$__permit_f" fi done [ "$__permit_v" = 0 ] || [ "$#" = 0 ] || printf >&2 'notice: +x %s\n' "$@" [ "$__permit_n" = 1 ] || [ "$#" = 0 ] || chmod +x -- "$@" || __permit_x=$? return "$__permit_x" } [ -n "${preload+-}" ] || permit "$@"