2 # Desc: Scan file system and update '.hidden' files to hide certain 
   3 #   files based on filenames. 
   5 # Usage: bk-naut-hide [DIRS...] 
   7 yell
() { echo "$0: $*" >&2; } # print script path and all args to stderr 
   8 die
() { yell 
"$*"; exit 111; } # same as yell() but non-zero exit status 
   9 try
() { "$@" || die 
"cannot $*"; } # runs args as command, reports args if command fails 
  11     # Desc: If arg is a command, save result in assoc array 'appRollCall' 
  12     # Usage: checkapp arg1 arg2 arg3 ... 
  14     # Input: global assoc. array 'appRollCall' 
  15     # Output: adds/updates key(value) to global assoc array 'appRollCall' 
  21         if command -v "$arg" 1>/dev
/null 
2>&1; then # Check if arg is a valid command 
  22             appRollCall
[$arg]="true"; 
  23             if ! [ "$returnState" = "false" ]; then returnState
="true"; fi; 
  25             appRollCall
[$arg]="false"; returnState
="false"; 
  29     #===Determine function return code=== 
  30     if [ "$returnState" = "true" ]; then 
  35 } # Check that app exists 
  37     # Desc: If arg is a file path, save result in assoc array 'fileRollCall' 
  38     # Usage: checkfile arg1 arg2 arg3 ... 
  40     # Input: global assoc. array 'fileRollCall' 
  41     # Output: adds/updates key(value) to global assoc array 'fileRollCall'; 
  42     # Output: returns 0 if app found, 1 otherwise 
  48         if [ -f "$arg" ]; then 
  49             fileRollCall
["$arg"]="true"; 
  50             if ! [ "$returnState" = "false" ]; then returnState
="true"; fi; 
  52             fileRollCall
["$arg"]="false"; returnState
="false"; 
  56     #===Determine function return code=== 
  57     if [ "$returnState" = "true" ]; then 
  62 } # Check that file exists 
  64     # Desc: If arg is a dir path, save result in assoc array 'dirRollCall' 
  65     # Usage: checkdir arg1 arg2 arg3 ... 
  67     # Input: global assoc. array 'dirRollCall' 
  68     # Output: adds/updates key(value) to global assoc array 'dirRollCall'; 
  69     # Output: returns 0 if all args are dirs; 1 otherwise 
  75         if [ -z "$arg" ]; then 
  76             dirRollCall
["(Unspecified Dirname(s))"]="false"; returnState
="false"; 
  77         elif [ -d "$arg" ]; then 
  78             dirRollCall
["$arg"]="true"; 
  79             if ! [ "$returnState" = "false" ]; then returnState
="true"; fi 
  81             dirRollCall
["$arg"]="false"; returnState
="false"; 
  85     #===Determine function return code=== 
  86     if [ "$returnState" = "true" ]; then 
  91 } # Check that dir exists 
  93     # Desc: Displays missing apps, files, and dirs 
  94     # Usage: displayMissing 
  96     # Input: associative arrays: appRollCall, fileRollCall, dirRollCall 
  97     # Output: stderr: messages indicating missing apps, file, or dirs 
  98     # Output: returns exit code 0 if nothing missing; 1 otherwise 
  99     # Depends: bash 5, checkAppFileDir() 
 100     local missingApps value appMissing missingFiles fileMissing
 
 101     local missingDirs dirMissing
 
 103     #==BEGIN Display errors== 
 104     #===BEGIN Display Missing Apps=== 
 105     missingApps
="Missing apps  :"; 
 106     #for key in "${!appRollCall[@]}"; do echo "DEBUG:$key => ${appRollCall[$key]}"; done 
 107     for key 
in "${!appRollCall[@]}"; do 
 108         value
="${appRollCall[$key]}"; 
 109         if [ "$value" = "false" ]; then 
 110             #echo "DEBUG:Missing apps: $key => $value"; 
 111             missingApps
="$missingApps""$key "; 
 115     if [ "$appMissing" = "true" ]; then  # Only indicate if an app is missing. 
 116         echo "$missingApps" 1>&2; 
 119     #===END Display Missing Apps=== 
 121     #===BEGIN Display Missing Files=== 
 122     missingFiles
="Missing files:"; 
 123     #for key in "${!fileRollCall[@]}"; do echo "DEBUG:$key => ${fileRollCall[$key]}"; done 
 124     for key 
in "${!fileRollCall[@]}"; do 
 125         value
="${fileRollCall[$key]}"; 
 126         if [ "$value" = "false" ]; then 
 127             #echo "DEBUG:Missing files: $key => $value"; 
 128             missingFiles
="$missingFiles""$key "; 
 132     if [ "$fileMissing" = "true" ]; then  # Only indicate if an app is missing. 
 133         echo "$missingFiles" 1>&2; 
 136     #===END Display Missing Files=== 
 138     #===BEGIN Display Missing Directories=== 
 139     missingDirs
="Missing dirs:"; 
 140     #for key in "${!dirRollCall[@]}"; do echo "DEBUG:$key => ${dirRollCall[$key]}"; done 
 141     for key 
in "${!dirRollCall[@]}"; do 
 142         value
="${dirRollCall[$key]}"; 
 143         if [ "$value" = "false" ]; then 
 144             #echo "DEBUG:Missing dirs: $key => $value"; 
 145             missingDirs
="$missingDirs""$key "; 
 149     if [ "$dirMissing" = "true" ]; then  # Only indicate if an dir is missing. 
 150         echo "$missingDirs" 1>&2; 
 153     #===END Display Missing Directories=== 
 155     #==END Display errors== 
 156     #==BEGIN Determine function return code=== 
 157     if [ "$appMissing" == "true" ] || 
[ "$fileMissing" == "true" ] || 
[ "$dirMissing" == "true" ]; then 
 162     #==END Determine function return code=== 
 163 } # Display missing apps, files, dirs 
 164 get_paths_dothide
() { 
 165     # Desc: Recursively search specified ir for '.hidden' files 
 166     # Usage: get_paths_dothide arg1 
 167     # Input: arg1     dir to search 
 168     # Output: stdout  list of paths of '.hidden' files 
 172     if [[ $# -ne 1 ]]; then die 
"FATAL:Arg count does not equal 1:$#"; fi; 
 173     if [[ ! -d "$1" ]]; then die 
"FATAL:Not a dir:$1"; fi; 
 175     # Search for files named '.hidden' 
 176     find "$1" -type f 
-name ".hidden" 2>/dev
/null
 
 177 }; # Return list of paths of '.hidden' files 
 180     local -a dirs_target pat_tohide
 
 183     # check and specify list of dirs to search 
 185         if [[ -d $arg ]]; then             
 186             dirs_target
+=("$arg"); 
 188             die 
"FATAL:Not a dir:arg:$arg"; 
 191     #yell "DEBUG:dirs_target:${dirs_target[*]}"; 
 193     # specify filename regex patterns to mark '.hidden' 
 194     pat_tohide
+=(".ots$"); 
 195     pat_tohide
+=(".ots.bak$"); 
 196     #yell "DEBUG:pat_tohide:${pat_tohide[*]}"; 
 198     # generate list of paths of '.hidden' files 
 199     for dir 
in "${dirs_target[@]}"; do 
 200         #yell "DEBUG:generating list of paths of '.hidden' files in dir:$dir"; 
 201         while read -r file; do 
 202             ls_dothide_f
+=("$file"); 
 203         done < <(get_paths_dothide 
"$dir"); 
 205     #yell "DEBUG:ls_dothide_f:${ls_dothide_f[*]}"; 
 208     # get list of dirs containing the files 
 209     while read -r line
; do 
 210         #yell "DEBUG:found .hidden file at:$line"; 
 211         dir
="$(dirname "$line")"; 
 212         ls_dothide_d
+=("$dir"); 
 213     done < <(printf "%s\n" "${ls_dothide_f[@]}") 
 214     #yell "DEBUG:ls_dothide_d:${ls_dothide_d[*]}"; 
 217     # for each dir, write list of files to hide in '.hidden' 
 218     while read -r dir
; do 
 219         #yell "DEBUG:performing actions in dir:$dir"; 
 220         declare -a ls_tohide_fn
; # array for filenames to write in '.hidden' 
 223         while read -r file; do 
 224             #yell "DEBUG:considering file:$file"; 
 225             filename
="$(basename "$file")"; 
 227             ## check if file is actually a file 
 228             if [[ ! -f $file ]]; then continue; fi;             
 230             ## check if file should be hidden according to pattern match 
 231             unset flag_pat_match
; 
 232             while read -r pat
; do 
 233                 if [[ $filename =~ 
$pat ]]; then 
 234                     flag_pat_match
="true"; 
 235                     break; # don't consider any more patterns for this file 
 237                     flag_pat_match
="false"; 
 239             done < <(printf "%s\n" "${pat_tohide[@]}"); 
 241             ## add file to list to add to '.hidden' 
 242             if [[ $flag_pat_match == "true" ]]; then 
 243                 #yell "DEBUG:adding to ls_tohide_fn:file:$file": 
 244                 #yell "DEBUG:filename:$filename"; 
 245                 ls_tohide_fn
+=("$filename"); 
 249             ## unset variables defined only for this file 
 250             unset filename flag_pat_match
; 
 251         done < <(find "$dir" -mindepth 1 -maxdepth 1 -type f 
2>/dev
/null
); 
 254         ## add file names to $dir/'.hidden' 
 255         ### remove blank lines and sort and uniq 
 256         while read -r line
; do 
 257               ls_tohide_fn_sortuniq
+=("$line"); 
 258         done < <(printf "%s\n" "${ls_tohide_fn[@]}" | 
sed '/^$/d' | 
sort | 
uniq); 
 259         ls_tohide_fn
=("${ls_tohide_fn_sortuniq[@]}"); 
 262         path_hidefile
="$dir"/.hidden
; 
 263         #yell "DEBUG:Writing contents of .hidden file at path_hidefile:$path_hidefile"; 
 264         #yell "DEBUG:ls_tohide_fn:$(printf "%s\n" "${ls_tohide_fn[@]}" )"; 
 265         printf "%s\n" "${ls_tohide_fn[@]}" > "$path_hidefile" 
 267         ## unset variables defined only for this dir 
 268         unset ls_tohide_fn path_hidefile
; 
 271     done < <(printf "%s\n" "${ls_dothide_d[@]}");