Commit | Line | Data |
---|---|---|
211b1458 SBS |
1 | #!/usr/bin/env bash |
2 | # Desc: Scan file system and update '.hidden' files to hide certain | |
3 | # files based on filenames. | |
e2912511 | 4 | # Version: 0.0.2 |
211b1458 SBS |
5 | # Usage: bk-naut-hide [DIRS...] |
6 | ||
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 | |
10 | checkapp() { | |
11 | # Desc: If arg is a command, save result in assoc array 'appRollCall' | |
12 | # Usage: checkapp arg1 arg2 arg3 ... | |
13 | # Version: 0.1.1 | |
14 | # Input: global assoc. array 'appRollCall' | |
15 | # Output: adds/updates key(value) to global assoc array 'appRollCall' | |
16 | # Depends: bash 5.0.3 | |
17 | local returnState | |
18 | ||
19 | #===Process Args=== | |
20 | for arg in "$@"; do | |
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; | |
24 | else | |
25 | appRollCall[$arg]="false"; returnState="false"; | |
26 | fi; | |
27 | done; | |
28 | ||
29 | #===Determine function return code=== | |
30 | if [ "$returnState" = "true" ]; then | |
31 | return 0; | |
32 | else | |
33 | return 1; | |
34 | fi; | |
35 | } # Check that app exists | |
36 | checkfile() { | |
37 | # Desc: If arg is a file path, save result in assoc array 'fileRollCall' | |
38 | # Usage: checkfile arg1 arg2 arg3 ... | |
39 | # Version: 0.1.1 | |
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 | |
43 | # Depends: bash 5.0.3 | |
44 | local returnState | |
45 | ||
46 | #===Process Args=== | |
47 | for arg in "$@"; do | |
48 | if [ -f "$arg" ]; then | |
49 | fileRollCall["$arg"]="true"; | |
50 | if ! [ "$returnState" = "false" ]; then returnState="true"; fi; | |
51 | else | |
52 | fileRollCall["$arg"]="false"; returnState="false"; | |
53 | fi; | |
54 | done; | |
55 | ||
56 | #===Determine function return code=== | |
57 | if [ "$returnState" = "true" ]; then | |
58 | return 0; | |
59 | else | |
60 | return 1; | |
61 | fi; | |
62 | } # Check that file exists | |
63 | checkdir() { | |
64 | # Desc: If arg is a dir path, save result in assoc array 'dirRollCall' | |
65 | # Usage: checkdir arg1 arg2 arg3 ... | |
66 | # Version 0.1.2 | |
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 | |
70 | # Depends: Bash 5.0.3 | |
71 | local returnState | |
72 | ||
73 | #===Process Args=== | |
74 | for arg in "$@"; do | |
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 | |
80 | else | |
81 | dirRollCall["$arg"]="false"; returnState="false"; | |
82 | fi | |
83 | done | |
84 | ||
85 | #===Determine function return code=== | |
86 | if [ "$returnState" = "true" ]; then | |
87 | return 0; | |
88 | else | |
89 | return 1; | |
90 | fi | |
91 | } # Check that dir exists | |
92 | displayMissing() { | |
93 | # Desc: Displays missing apps, files, and dirs | |
94 | # Usage: displayMissing | |
95 | # Version 1.0.0 | |
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 | |
102 | ||
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 "; | |
112 | appMissing="true"; | |
113 | fi; | |
114 | done; | |
115 | if [ "$appMissing" = "true" ]; then # Only indicate if an app is missing. | |
116 | echo "$missingApps" 1>&2; | |
117 | fi; | |
118 | unset value; | |
119 | #===END Display Missing Apps=== | |
120 | ||
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 "; | |
129 | fileMissing="true"; | |
130 | fi; | |
131 | done; | |
132 | if [ "$fileMissing" = "true" ]; then # Only indicate if an app is missing. | |
133 | echo "$missingFiles" 1>&2; | |
134 | fi; | |
135 | unset value; | |
136 | #===END Display Missing Files=== | |
137 | ||
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 "; | |
146 | dirMissing="true"; | |
147 | fi; | |
148 | done; | |
149 | if [ "$dirMissing" = "true" ]; then # Only indicate if an dir is missing. | |
150 | echo "$missingDirs" 1>&2; | |
151 | fi; | |
152 | unset value; | |
153 | #===END Display Missing Directories=== | |
154 | ||
155 | #==END Display errors== | |
156 | #==BEGIN Determine function return code=== | |
157 | if [ "$appMissing" == "true" ] || [ "$fileMissing" == "true" ] || [ "$dirMissing" == "true" ]; then | |
158 | return 1; | |
159 | else | |
160 | return 0; | |
161 | fi | |
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 | |
169 | ||
170 | local | |
171 | # Check input | |
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; | |
174 | ||
175 | # Search for files named '.hidden' | |
176 | find -L "$1" -type f -name ".hidden" 2>/dev/null | |
177 | }; # Return list of paths of '.hidden' files | |
178 | ||
179 | main() { | |
180 | local -a dirs_target pat_tohide | |
181 | ||
182 | # check input | |
183 | # check and specify list of dirs to search | |
184 | for arg in "$@"; do | |
185 | if [[ -d $arg ]]; then | |
186 | dirs_target+=("$arg"); | |
187 | else | |
188 | die "FATAL:Not a dir:arg:$arg"; | |
189 | fi; | |
190 | done; | |
e2912511 | 191 | #yell "DEBUG:dirs_target:${dirs_target[*]}"; |
211b1458 SBS |
192 | |
193 | # specify filename regex patterns to mark '.hidden' | |
194 | pat_tohide+=(".ots$"); | |
195 | pat_tohide+=(".ots.bak$"); | |
e2912511 | 196 | #yell "DEBUG:pat_tohide:${pat_tohide[*]}"; |
211b1458 SBS |
197 | |
198 | # generate list of paths of '.hidden' files | |
199 | for dir in "${dirs_target[@]}"; do | |
e2912511 | 200 | #yell "DEBUG:generating list of paths of '.hidden' files in dir:$dir"; |
211b1458 SBS |
201 | while read -r file; do |
202 | ls_dothide_f+=("$file"); | |
203 | done < <(get_paths_dothide "$dir"); | |
204 | done; | |
e2912511 SBS |
205 | #yell "DEBUG:ls_dothide_f:${ls_dothide_f[*]}"; |
206 | #yell "DEBUG:"; | |
211b1458 SBS |
207 | |
208 | # get list of dirs containing the files | |
209 | while read -r line; do | |
e2912511 | 210 | #yell "DEBUG:found .hidden file at:$line"; |
211b1458 SBS |
211 | dir="$(dirname "$line")"; |
212 | ls_dothide_d+=("$dir"); | |
213 | done < <(printf "%s\n" "${ls_dothide_f[@]}") | |
e2912511 SBS |
214 | #yell "DEBUG:ls_dothide_d:${ls_dothide_d[*]}"; |
215 | #yell "DEBUG:"; | |
211b1458 SBS |
216 | |
217 | # for each dir, write list of files to hide in '.hidden' | |
218 | while read -r dir; do | |
e2912511 | 219 | #yell "DEBUG:performing actions in dir:$dir"; |
211b1458 SBS |
220 | declare -a ls_tohide_fn; # array for filenames to write in '.hidden' |
221 | ||
222 | ## act on each file | |
223 | while read -r file; do | |
e2912511 | 224 | #yell "DEBUG:considering file:$file"; |
211b1458 SBS |
225 | filename="$(basename "$file")"; |
226 | ||
227 | ## check if file is actually a file | |
228 | if [[ ! -f $file ]]; then continue; fi; | |
229 | ||
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 | |
236 | else | |
237 | flag_pat_match="false"; | |
238 | fi; | |
239 | done < <(printf "%s\n" "${pat_tohide[@]}"); | |
240 | ||
241 | ## add file to list to add to '.hidden' | |
242 | if [[ $flag_pat_match == "true" ]]; then | |
e2912511 SBS |
243 | #yell "DEBUG:adding to ls_tohide_fn:file:$file": |
244 | #yell "DEBUG:filename:$filename"; | |
211b1458 SBS |
245 | ls_tohide_fn+=("$filename"); |
246 | fi; | |
e2912511 | 247 | #yell "DEBUG:"; |
211b1458 SBS |
248 | |
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); | |
e2912511 | 252 | #yell "DEBUG:"; |
211b1458 SBS |
253 | |
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[@]}"); | |
260 | ||
261 | ### write '.hidden' | |
262 | path_hidefile="$dir"/.hidden; | |
e2912511 SBS |
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[@]}" )"; | |
211b1458 SBS |
265 | printf "%s\n" "${ls_tohide_fn[@]}" > "$path_hidefile" |
266 | ||
267 | ## unset variables defined only for this dir | |
268 | unset ls_tohide_fn path_hidefile; | |
269 | ||
e2912511 | 270 | #yell "DEBUG:"; |
211b1458 SBS |
271 | done < <(printf "%s\n" "${ls_dothide_d[@]}"); |
272 | }; # main program | |
273 | ||
274 | main "$@"; |