From b64bbf81557962c5076f432250f38d6c9c25819d Mon Sep 17 00:00:00 2001 From: Steven Baltakatei Sandoval Date: Sat, 30 Apr 2022 02:08:45 +0000 Subject: [PATCH] feat(user/bkots):Add script to run ots recursively --- doc/user/bkots..flowchart.odg | Bin 0 -> 24436 bytes unitproc/bktemp-get_parent_dirnames | 36 ++ unitproc/bktemp-processArgs | 59 ++- user/bkots | 658 ++++++++++++++++++++++++++++ 4 files changed, 732 insertions(+), 21 deletions(-) create mode 100644 doc/user/bkots..flowchart.odg create mode 100644 unitproc/bktemp-get_parent_dirnames create mode 100644 user/bkots diff --git a/doc/user/bkots..flowchart.odg b/doc/user/bkots..flowchart.odg new file mode 100644 index 0000000000000000000000000000000000000000..ea0787db2800ec01800885143626877afb9d1697 GIT binary patch literal 24436 zcmb5U18^olvnU#FY}>Y-Y;4=MZEIs=W81c^jcw;kz8D+7{qL=NU%jeR=hf+{sp&ya z_tZ>Jbyv5NEI0%@2naL?2oy@5T0S`A2ptFr$bag;ArO0OdviB$Cv#&bCp&9XV>fF@ z2PO{(Ge$>aS8G>BM<;U!Ge=W*dvgajMoSlCCo5}HSEc{YhX3~XzkvM@6Loa3u(ot} z`CnVPvNE|jI@*~SyDkEzA3CD{f}^#)v8A~ylZdsOy|I()|4>|G zQ&V$0^MCj0_+EwbM>^*omk`86P*IcjgA&cp6dz5$4Fjbcy-0+k9Fr-i+;e}Ek1#f@ zTVlyxfjw5=5GAj7j?+`I_u@ckehmy-OOYklIsWMP|Cr20=nMRe)O2elB{2|V-=^d~ zahM}A&EYF@&0<1NQt@G1cgkbnPq5%tuhmSg?Jd0dBk;sO@2@12oIRLc3K#8?%%qaK z?>9IM>BeD#Nx^hz5(38~w310he$5AR+eISJ$}+_|_RNek+-a0L{6a8yZJK~_`uYnC z`^uxcdPfTIeHRMFo^b?qjpLAhhuK3(IE-Vy?IdYDm}9R^zfm+l%n}iGV&H^(~?h3j7?(V2}vxd+h0S|nO2kRNyxw-~X+q)jHeZdI8ZUfRqyL8mVcw8(AnMs(GVhd_#x{r{!;abZcWgyo`2O zk{ZS0zzvvSCi^MUc-2-B>l7rR$(%0tY+?^Y{!4g^{lyVe)G>!OI!~rJLJ^$gt9X0O zw?tM(RZ*Ecf?IgV%x;}2vJZoZwI`}azX~zfcvmmdty7rVC4HT&R->E6P_x_SbjQ2N zPCxeBlkV4j{g&rRvRUt*$AE6sI0>2dja5YlU6Sc=ijHmN1n6>bF=!(vSn;6k!>Xb3 z-I!q^ayJU%(Z>^AD@e43q`+{C!w<(hs>g&{*GLu6J}+Tx&O6wE9-I#tbN27%(PG>m z3g%M#?rYo_7AS@MfipY`wDdR!h0Fs2CStrzYl7wZ*kcH2O;Q;-gM6eWv5#(N>18b_ zzXkdT&&k<`=mn0pLo9!9NAvHW|N7nfwnS){5XF*J;2Qjc)Hit5)xom$JQv$_#nxru zFaAVtc}`n)^S;;W1-IkZ8`s&j{7Vh{(FSS88oGsh_f)Gve~4y-*Gti_Ursj@R0O+H z_%Wj;S=cF-&);@Rs*G4=*>qk?DMX&(#ZcVINog&&oV!7oNxXpBnGe%}ci8auk{iyr~<*5BgpL>C^?OHE!QhB523$5DtF}t-_PfmTXm#GBul*1Pv z)pYO8Uf(75o15?g%e@8>OVV*&gSS4s_yO+jLg)cH)mM?l+g`Zx#k^d3NTDEs?&{xB zN14}~EwxUM%G^UK-f=_IcTY1!ffV64oYceK>M#+aj1t>p;gko%vqmaXa74iJs`NBs zGh1yKUB$&F{Yi+%Kbae}Ujx{gFuQPxD<4wftbIp(qI)>6Rr<%6?ZH+tJ0Q4RqTjM> zL3pu6`1lmJwz(x{E@1rzZ}Z8Biq8ApMLa>@L?lAzsYH5eUk$2Xw?+4ox%ZM-X+qbj zLVXn<(&ZnM;wOrHCyGq8-(9L-PZTGfS>HvgH|$^H_IuWEF*!@{L~1 zW}7RAhzBwrbNo;q54ew-7$W?Mbz&$dOvFT`+G#9Jw)d_P$J~__l)4N>>Aj8YhKtFq zmRpfU-Iy|HySY{duZ+d8eo zwAi@=ATR7$=}A}+ojdR;ti0NJWs^rz1okPm)9xv36#}G3wX4%EYfN8_jQMMDEgQ*bLJ#a#}L|61JU2Yy#O ziP|DhqnYQ2l{mzvhp2cBs8R28jMAVf#E$R5bngmK%HkrujWpP><0_i@oV8l}Kp+lN z?Gqa^U8B}h5B~_uh@3ySgNB^?V~8(u#74^Qn*=RC7cqZp^FfM|m4{Hc5HoW2=J&T} zo?CzqPvi&-xBSdf?A(0Jnpz5paVagEs4H*TAoJUnW+SC z8qP(m>xB7|6tYE11+UN8t$VlQtzf|JssBbT!uN0CW-M!X0Z-NTp0L1~^9;UYJS5d{w9xQx=Ikb5bE zLyIsVU01?TQQ8#iG~sBC4u({O6K$1P_Rz1vN>T1Ga!~8sx6k=KMqlEvz@fN=50z48V_q8)&MXiaA)cI2ovoi^CLTiObyL~H7m1=(Yjj+ z@l^t`t}m>7OHnI+`3OjR2xaA)LHUxW`9Lro>=$v{fHumE(x|?(!G;=hQUUyQlynRK z-pXYxXraNUz08drmNdS7SYx!UhjmMZY5cGbSRv>ktg*FuVv1M?nxNc>x{2 zY$GBZ$O!y$Opn>?()(~6OFLas&5#X^7j0zaP(f5(kf%fhdFf7bx@s}|dD-H7 zf~`%#3yS71-wT-vJI+>IWF~}>?nq0TYgCMM(q!A`|E+%YF!+Ue^_sJ)H{du}GIc-G zV0G{(Vy3?8uTSUxwm;FuR6ZnvXR_bxLzqpNa=kzVUL9JoSMWhnJKoBfl)s#PpB`^a zC7+2W=vdUkyBPc9nvDNEGZAMlLfja&wvn?+4nGRaCyOc(`HZKcrDzcYKc-O*F7f;R zLNj7Te;^<<=~WFNjopj(5D)?MYaUXJ54+Fe%KWQu3e;}mzEPlMqYLVKY^jgKB+@2u zJwPv4w(pPdEqjf)-nN(N5WMCktZk>>V;6@C*GxOw{)O}BS6J%sg|F`(+@)m4GGf0V zjT^$?j7gk6OJLUthW&TIC6bL70IBAL#!V>@ws);&t}S%4*?x)k#Ci#VF76cFm%G0U zG3KZ#76p{tyyOEz;Z`;Uo7BU{!Fs{&c#9hD8Tg}Mc-8>BU|__7zhNFVJbw*7pf+kQ za|J3wAiZkMicwxlY3`)Ri@yH{mW(i(o&d~do-)p&1cXtLiS}uH{ zBb;oIdT;2!xT*?qw~r7Oy_VicuW?b=-LX$kx->9-*VaDX`jTRvN9DOhBQK@bV#BU4*I4JfbogF^e>8po2xw9`;saP3dtklO zCGVUx^KrK5oH;)3lx7siKh5BT7|cErXhMis8;&9hKsa>)d3-Nr7TKW1(77h}*ldsQ6F_b~KWF zZ-*J`ZrN<5oJ;(aA2By%HCQ%sAcqryXxVb8)zGR9)o|)|D%tGQ{K`oh+CKg3CEW+0 z2cSU^cBZ|@nEWiXWzmryFJk_x)$iB7QRt6kyw4E_

2*s}cXD_H%P)9qmKlsudz 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 X{A#F!hyQIi@{8BEDO%L>+t&X8152L7 literal 0 HcmV?d00001 diff --git a/unitproc/bktemp-get_parent_dirnames b/unitproc/bktemp-get_parent_dirnames new file mode 100644 index 0000000..1a5184f --- /dev/null +++ b/unitproc/bktemp-get_parent_dirnames @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# Desc: Provides newline-delimited list of each parent dir + +yell() { echo "$0: $*" >&2; } # print script path and all args to stderr +die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status +try() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails +get_parent_dirnames() { + # Desc: Provides newline-delimited list of each parent dir of a file or dir + # Usage: get_parent_dirnames arg1 + # Input: arg1 input path + # Output: stdout newline-delimited list of parent dirs + # Version: 0.0.1 + # Depends: yell(), die(), try() + local path + + # Check input + if [[ $# -ne 1 ]]; then die "FATAL:Incorrect number of arguments:$#"; fi; + if ! { [[ -f $1 ]] || [[ -d $1 ]]; }; then die "FATAL:Not a file or dir:$1"; fi; + + # Process path + path="$1"; + while [[ -f $path ]] || [[ -d $path ]]; do + path="$(dirname "$path")"; + name_base_previous="$name_base"; + name_base="$(basename "$path")"; + ## Check for stop condition (dirname returns same result as previous iteration) + if [[ $name_base == "$name_base_previous" ]]; then break; fi; + echo "$name_base"; + done; +}; # Output parent dirnames to stdout + +# Test code +sleep 1 && get_parent_dirnames /home/baltakatei/Downloads/ & # should work +sleep 2 && get_parent_dirnames /home/baltakatei/Downloads/ foo & # should fail +sleep 3 && get_parent_dirnames bar/baz & # should fail +sleep 4; diff --git a/unitproc/bktemp-processArgs b/unitproc/bktemp-processArgs index ca29c35..27679a2 100644 --- a/unitproc/bktemp-processArgs +++ b/unitproc/bktemp-processArgs @@ -4,6 +4,7 @@ #==BEGIN Define script parameters== #===BEGIN Define variables=== : +declare -ag arrayPosArgs #===END Define variables=== #===BEGIN Declare local script functions=== @@ -17,7 +18,7 @@ vbm() { # Input: arg1: string # vars: opVerbose # Output: stderr - # Depends: bash 5.0.3, GNU-coreutils 8.30 (echo, date) + # Depends: bash 5.1.16, GNU-coreutils 8.30 (echo, date) if [ "$opVerbose" = "true" ]; then functionTime="$(date --iso-8601=ns)"; # Save current time in nano seconds. @@ -30,7 +31,7 @@ vbm() { showUsage() { # Desc: Display script usage information # Usage: showUsage - # Version 0.0.1 + # Version 0.0.2 # Input: none # Output: stdout # Depends: GNU-coreutils 8.30 (cat) @@ -50,18 +51,21 @@ showUsage() { -I, --input-dir Define input directory path. -o, --output-file - Define output file path + Define output file path. -O, --output-dir - Define output directory path + Define output directory path. + -- + Indicate end of options. EXAMPLE: bktemp-processArgs -o foo.txt + bktemp-processArgs -o foo.txt -- some_file.txt EOF } # Display information on how to use this script. showVersion() { # Desc: Displays script version and license information. # Usage: showVersion - # Version: 0.0.1 + # Version: 0.0.2 # Input: scriptVersion var containing version string # Output: stdout # Depends: vbm(), yell, GNU-coreutils 8.30 @@ -70,14 +74,14 @@ showVersion() { vbm "DEBUG:showVersion function called." cat <<'EOF' -bktemp-processArgs 0.0.1 +bktemp-processArgs 1.0.0 Copyright (C) 2021 Steven Baltakatei Sandoval License GPLv3: GNU GPL version 3 This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. - GNU Coreutils 8.30 - Copyright (C) 2018 Free Software Foundation, Inc. + GNU Coreutils 8.32 + Copyright (C) 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later . This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. @@ -90,7 +94,7 @@ EOF processArgs() { # Desc: Processes arguments provided to script. # Usage: processArgs "$@" - # Version: 0.0.1 + # Version: 1.0.0 # Input: "$@" (list of arguments provided to the function) # Output: Sets following variables used by other functions: # opVerbose Indicates verbose mode enable status. (ex: "true", "false") @@ -98,15 +102,18 @@ processArgs() { # pathFileOut1 Path to output file. # pathDirIn1 Path to input directory. # pathFileIn1 Path to input file. - # opFileOut1_overwrite Indicates whether file pathFileOut1 should be overwritten (ex: "true", "false') + # opFileOut1_overwrite Indicates whether file pathFileOut1 should be overwritten (ex: "true", "false"). + # arrayPosArgs Array of remaining positional argments # Depends: # yell() Displays messages to stderr. # vbm() Displays messsages to stderr if opVerbose set to "true". - # showUsage() Displays usage information about parent script - # showVersion() Displays version about parent script - # External dependencies: bash (5.0.3), echo + # showUsage() Displays usage information about parent script. + # showVersion() Displays version about parent script. + # arrayPosArgs Global array for storing non-option positional arguments (i.e. arguments following the `--` option). + # External dependencies: bash (5.1.16), echo # Ref./Attrib.: # [1]: Marco Aurelio (2014-05-08). "echo that outputs to stderr". https://stackoverflow.com/a/23550347 + # [2]: "Handling positional parameters" (2018-05-12). https://wiki.bash-hackers.org/scripting/posparams # Initialize function vbm "DEBUG:processArgs function called." @@ -169,8 +176,16 @@ processArgs() { yell "ERROR:Specified output directory is not valid:""$2"; yell "Exiting."; exit 1; - fi ;; - *) yell "ERROR: Unrecognized argument."; exit 1;; # Handle unrecognized options. See [1]. + fi ;; + --) # End of all options. See [2]. + shift; + for arg in "$@"; do + vbm "DEBUG:adding to arrayPosArgs:$arg"; + arrayPosArgs+=("$arg"); + done; + break;; + -*) showUsage; yell "ERROR: Unrecognized option."; exit 1;; # Display usage + *) showUsage; yell "ERROR: Unrecognized argument."; exit 1;; # Handle unrecognized options. See [1]. esac shift done @@ -186,12 +201,14 @@ processArgs() { #==BEGIN sample code== processArgs "$@"; yell "DEBUG:Provided arguments..:""$*" -yell "DEBUG:opVerbose...........:$opVerbose"; -yell "DEBUG:pathDirOut1.........:$pathDirOut1"; -yell "DEBUG:pathFileOut1........:$pathFileOut1"; -yell "DEBUG:pathDirIn1..........:$pathDirIn1"; -yell "DEBUG:pathFileIn1.........:$pathFileIn1"; -yell "DEBUG:opFileOut1_overwrite:$opFileOut1_overwrite"; +yell "DEBUG:opVerbose...........:${opVerbose:-}"; +yell "DEBUG:pathDirOut1.........:${pathDirOut1:-}"; +yell "DEBUG:pathFileOut1........:${pathFileOut1:-}"; +yell "DEBUG:pathDirIn1..........:${pathDirIn1:-}"; +yell "DEBUG:pathFileIn1.........:${pathFileIn1:-}"; +yell "DEBUG:opFileOut1_overwrite:${opFileOut1_overwrite:-}"; +yell "DEBUG:arrayPosArgs........:$(if [[ -v arrayPosArgs ]]; then declare -p arrayPosArgs; else printf ""; fi )"; +#yell "DEBUG:arrayPosArgs........:${arrayPosArgs[*]}"; #==END sample code== # Author: Steven Baltaktei Sandoval diff --git a/user/bkots b/user/bkots new file mode 100644 index 0000000..fa9b7da --- /dev/null +++ b/user/bkots @@ -0,0 +1,658 @@ +#!/usr/bin/env bash + +# Define variables +declare -Ag appRollCall # Associative array for storing app status +declare -Ag fileRollCall # Associative array for storing file status +declare -Ag dirRollCall # Associative array for storing dir status +declare -ag arrayPosArgs # Associative array for processArgs() function + +# Declare functions +yell() { echo "$0: $*" >&2; } # print script path and all args to stderr +die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status +try() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails +checkapp() { + # Desc: If arg is a command, save result in assoc array 'appRollCall' + # Usage: checkapp arg1 arg2 arg3 ... + # Version: 0.1.1 + # Input: global assoc. array 'appRollCall' + # Output: adds/updates key(value) to global assoc array 'appRollCall' + # Depends: bash 5.0.3 + local returnState + + #===Process Args=== + for arg in "$@"; do + if command -v "$arg" 1>/dev/null 2>&1; then # Check if arg is a valid command + appRollCall[$arg]="true"; + if ! [ "$returnState" = "false" ]; then returnState="true"; fi; + else + appRollCall[$arg]="false"; returnState="false"; + fi; + done; + + #===Determine function return code=== + if [ "$returnState" = "true" ]; then + return 0; + else + return 1; + fi; +} # Check that app exists +checkfile() { + # Desc: If arg is a file path, save result in assoc array 'fileRollCall' + # Usage: checkfile arg1 arg2 arg3 ... + # Version: 0.1.1 + # Input: global assoc. array 'fileRollCall' + # Output: adds/updates key(value) to global assoc array 'fileRollCall'; + # Output: returns 0 if app found, 1 otherwise + # Depends: bash 5.0.3 + local returnState + + #===Process Args=== + for arg in "$@"; do + if [ -f "$arg" ]; then + fileRollCall["$arg"]="true"; + if ! [ "$returnState" = "false" ]; then returnState="true"; fi; + else + fileRollCall["$arg"]="false"; returnState="false"; + fi; + done; + + #===Determine function return code=== + if [ "$returnState" = "true" ]; then + return 0; + else + return 1; + fi; +} # Check that file exists +checkdir() { + # Desc: If arg is a dir path, save result in assoc array 'dirRollCall' + # Usage: checkdir arg1 arg2 arg3 ... + # Version 0.1.2 + # Input: global assoc. array 'dirRollCall' + # Output: adds/updates key(value) to global assoc array 'dirRollCall'; + # Output: returns 0 if all args are dirs; 1 otherwise + # Depends: Bash 5.0.3 + local returnState + + #===Process Args=== + for arg in "$@"; do + if [ -z "$arg" ]; then + dirRollCall["(Unspecified Dirname(s))"]="false"; returnState="false"; + elif [ -d "$arg" ]; then + dirRollCall["$arg"]="true"; + if ! [ "$returnState" = "false" ]; then returnState="true"; fi + else + dirRollCall["$arg"]="false"; returnState="false"; + fi + done + + #===Determine function return code=== + if [ "$returnState" = "true" ]; then + return 0; + else + return 1; + fi +} # Check that dir exists +displayMissing() { + # Desc: Displays missing apps, files, and dirs + # Usage: displayMissing + # Version 1.0.0 + # Input: associative arrays: appRollCall, fileRollCall, dirRollCall + # Output: stderr: messages indicating missing apps, file, or dirs + # Output: returns exit code 0 if nothing missing; 1 otherwise + # Depends: bash 5, checkAppFileDir() + local missingApps value appMissing missingFiles fileMissing + local missingDirs dirMissing + + #==BEGIN Display errors== + #===BEGIN Display Missing Apps=== + missingApps="Missing apps :"; + #for key in "${!appRollCall[@]}"; do echo "DEBUG:$key => ${appRollCall[$key]}"; done + for key in "${!appRollCall[@]}"; do + value="${appRollCall[$key]}"; + if [ "$value" = "false" ]; then + #echo "DEBUG:Missing apps: $key => $value"; + missingApps="$missingApps""$key "; + appMissing="true"; + fi; + done; + if [ "$appMissing" = "true" ]; then # Only indicate if an app is missing. + echo "$missingApps" 1>&2; + fi; + unset value; + #===END Display Missing Apps=== + + #===BEGIN Display Missing Files=== + missingFiles="Missing files:"; + #for key in "${!fileRollCall[@]}"; do echo "DEBUG:$key => ${fileRollCall[$key]}"; done + for key in "${!fileRollCall[@]}"; do + value="${fileRollCall[$key]}"; + if [ "$value" = "false" ]; then + #echo "DEBUG:Missing files: $key => $value"; + missingFiles="$missingFiles""$key "; + fileMissing="true"; + fi; + done; + if [ "$fileMissing" = "true" ]; then # Only indicate if an app is missing. + echo "$missingFiles" 1>&2; + fi; + unset value; + #===END Display Missing Files=== + + #===BEGIN Display Missing Directories=== + missingDirs="Missing dirs:"; + #for key in "${!dirRollCall[@]}"; do echo "DEBUG:$key => ${dirRollCall[$key]}"; done + for key in "${!dirRollCall[@]}"; do + value="${dirRollCall[$key]}"; + if [ "$value" = "false" ]; then + #echo "DEBUG:Missing dirs: $key => $value"; + missingDirs="$missingDirs""$key "; + dirMissing="true"; + fi; + done; + if [ "$dirMissing" = "true" ]; then # Only indicate if an dir is missing. + echo "$missingDirs" 1>&2; + fi; + unset value; + #===END Display Missing Directories=== + + #==END Display errors== + #==BEGIN Determine function return code=== + if [ "$appMissing" == "true" ] || [ "$fileMissing" == "true" ] || [ "$dirMissing" == "true" ]; then + return 1; + else + return 0; + fi + #==END Determine function return code=== +} # Display missing apps, files, dirs +vbm() { + # Description: Prints verbose message ("vbm") to stderr if opVerbose is set to "true". + # Usage: vbm "DEBUG :verbose message here" + # Version 0.2.0 + # Input: arg1: string + # vars: opVerbose + # Output: stderr + # Depends: bash 5.0.3, GNU-coreutils 8.30 (echo, date) + + if [ "$opVerbose" = "true" ]; then + functionTime="$(date --iso-8601=ns)"; # Save current time in nano seconds. + echo "[$functionTime]:$0:""$*" 1>&2; # Display argument text. + fi + + # End function + return 0; # Function finished. +} # Displays message if opVerbose true +showVersion() { + # Desc: Displays script version and license information. + # Usage: showVersion + # Version: 0.0.1 + # Input: scriptVersion var containing version string + # Output: stdout + # Depends: vbm(), yell, GNU-coreutils 8.30 + + # Initialize function + vbm "DEBUG:showVersion function called." + + cat <<'EOF' +bkots 0.0.1 +Copyright (C) 2022 Steven Baltakatei Sandoval +License GPLv3: GNU GPL version 3 +This is free software; you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. + + GNU Coreutils 8.32 + Copyright (C) 2020 Free Software Foundation, Inc. + License GPLv3+: GNU GPL version 3 or later . + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. +EOF + + # End function + vbm "DEBUG:showVersion function ended." + return 0; # Function finished. +} # Display script version. +showUsage() { + # Desc: Display script usage information + # Usage: showUsage + # Version 0.0.1 + # Input: none + # Output: stdout + # Depends: GNU-coreutils 8.30 (cat) + cat <<'EOF' + USAGE: + bkots [ options ] [PATH...] + + POSITIONAL ARGUMENTS: + PATH Path(s) of file(s) or directory(ies) + + OPTIONS: + --dry-run + Do everything except run 'ots' commands. + -h, --help + Display help information. + --include-dotfiles + Include files and directories starting with '.' (not + included by default). + -r, --recursive + Consider files in dirs recursively. + --version + Display script version. + -v, --verbose + Display debugging info. + -- + Mark end of options. Interpret remaining arguments as + positional arguments. + + DESCRIPTION: + Scans files by file paths or directory paths provided by + positional arguments to see if Open Timestamps '.ots' file + exists. If so, attempt to upgrade and verify the '.ots' + file. If no '.ots' file exists, attempt to create one. + + Files with a dotfile parent directory located anywhere in the + file path are ignored by default. (e.g. 'HEAD' in + '/home/user/diary/.git/logs/HEAD' because of '.git'). Dotfiles + themselves are also ignored by default + (e.g. '/home/user/.gitconfig'). + + EXAMPLES: + bkots -v foo.txt + bkots foo.txt bar.pdf /home/username/Pictures/ +EOF +} # Display information on how to use this script. +processArgs() { + # Desc: Processes arguments provided to script. + # Usage: processArgs "$@" + # Version: 1.0.0 + # Input: "$@" (list of arguments provided to the function) + # Output: Sets following variables used by other functions: + # opVerbose Indicates verbose mode enable status. (ex: "true", "false") + # arrayPosArgs Array of remaining positional argments + # Depends: + # yell() Displays messages to stderr. + # vbm() Displays messsages to stderr if opVerbose set to "true". + # showUsage() Displays usage information about parent script. + # showVersion() Displays version about parent script. + # arrayPosArgs Global array for storing non-option positional arguments (i.e. arguments following the `--` option). + # External dependencies: bash (5.1.16), echo + # Ref./Attrib.: + # [1]: Marco Aurelio (2014-05-08). "echo that outputs to stderr". https://stackoverflow.com/a/23550347 + # [2]: "Handling positional parameters" (2018-05-12). https://wiki.bash-hackers.org/scripting/posparams + + # Initialize function + vbm "DEBUG:processArgs function called." + + # Perform work + while [ ! $# -eq 0 ]; do # While number of arguments ($#) is not (!) equal to (-eq) zero (0). + #yell "DEBUG:Starting processArgs while loop." # Debug stderr message. See [1]. + #yell "DEBUG:Provided arguments are:""$*" # Debug stderr message. See [1]. + case "$1" in + --dry-run) # Do not run ots commands + option_dry_run="true"; + vbm "DEBUG:Option enabled:dry run";; + -h | --help) showUsage; exit 1;; # Display usage. + --include-dotfiles) # Include dotfiles + option_include_dotfiles="true"; + vbm "DEBUG:Option enabled:include dotfiles";; + -r | --recursive) # Specify recursive option + option_recursive="true"; + vbm "DEBUG:option enabled:include files in dirs recursively";; + --version) showVersion; exit 1;; # Show version + -v | --verbose) opVerbose="true"; vbm "DEBUG:Verbose mode enabled.";; # Enable verbose mode. See [1]. + --) # End of all options. See [2]. + shift; + for arg in "$@"; do + vbm "DEBUG:adding to arrayPosArgs:$arg"; + arrayPosArgs+=("$arg"); + done; + break;; + -*) showUsage; yell "ERROR: Unrecognized option."; exit 1;; # Display usage + *) # Assume remaining arguments are positional arguments + for arg in "$@"; do + vbm "DEBUG:adding to arrayPosArgs:$arg"; + arrayPosArgs+=("$arg"); + done; + break;; + #*) showUsage; yell "ERROR: Unrecognized argument."; exit 1;; # Handle unrecognized options. See [1]. + esac + shift + done + + # End function + vbm "DEBUG:processArgs function ended." + return 0; # Function finished. +}; # Evaluate script options from positional arguments (ex: $1, $2, $3, etc.). +get_parent_dirnames() { + # Desc: Provides newline-delimited list of each parent dir of a file or dir + # Usage: get_parent_dirnames arg1 + # Input: arg1 input path + # Output: stdout newline-delimited list of parent dirs + # Version: 0.0.1 + # Depends: yell(), die(), try() + local path + + # Check input + if [[ $# -ne 1 ]]; then die "FATAL:Incorrect number of arguments:$#"; fi; + if ! { [[ -f $1 ]] || [[ -d $1 ]]; }; then die "FATAL:Not a file or dir:$1"; fi; + + # Process path + path="$1"; + while [[ -f $path ]] || [[ -d $path ]]; do + path="$(dirname "$path")"; + name_base_previous="$name_base"; + name_base="$(basename "$path")"; + ## Check for stop condition (dirname returns same result as previous iteration) + if [[ $name_base == "$name_base_previous" ]]; then break; fi; + echo "$name_base"; + done; +}; # Output parent dirnames to stdout +main() { + # Desc: Creates `.ots` file: + # - for each file specified in arrayPosArgs array + # - for each file in each dir specified in arrayPosArgs array + # Output file created alongside each file or in output directory specified by pathDirIn1 + # Usage: main "$@"; + # Input: arrayPosArgs array with positional arguments + # pathDirOut1 path for output `.ots` files (if pathDirOut1 is specified and is a path) + # Output: file(s) creates `.ots` file alongside specified files + # Depends: find (GNU findutils) 4.8.0, GNU Coreutils 8.32 (sort) + # Ref/Attrib: [1] How to create an array of unique elements from a string/array in bash https://unix.stackexchange.com/a/167194 + # [2] How to find files containing newlines in their names https://stackoverflow.com/a/21727028 + local -a file_list file_list_pruned; + local -a files_to_verify files_to_upgrade files_to_stamp + local -a files_to_verify_pruned files_to_upgrade_pruned files_to_stamp_pruned + + # Process args + processArgs "$@"; + + # Check dependencies + if ! checkapp ots find; then + displayMissing; + die "FATAL:Missing dependencies."; + fi; + + # Check arguments + ## Mark if output dir option specified + if [[ -v pathDirOut1 ]]; then + vbm "DEBUG:output directory specified:pathDirOut1:$pathDirOut1"; + if [[ -d $pathDirOut1 ]]; then + vbm "DEBUG:pathDirOut1:$pathDirOut1"; + config_output_dir="true"; + else + die "ERROR:Not a dir:$pathDirOut1"; + fi; + fi; + + # Display ots details + vbm "$(type ots)"; # show how 'ots' is defined + #TODO: add option to define 'ots' as a bash function that + #populates the ots option '--bitcoin-node FILE' with a + #user-specified FILE. + + # Populate file_list + vbm "DEBUG:begin populate file_list array"; + for item in "${arrayPosArgs[@]}"; do + vbm "DEBUG:adding to file list:item:$item"; + + ## Get full canonicalized path (follow symlinks) + item="$(readlink -f "$item")"; + vbm "DEBUG:item full path:item:$item"; + + ## Add to list: files + if [[ -f $item ]]; then + vbm "DEBUG:is a file:item:$item"; + file_list+=("$item"); + vbm "DEBUG:added to file_list:$item"; + ## Add to list: files in dirs + elif [[ -d $item ]]; then + vbm "DEBUG:is a dir:item:$item"; + ### Check for recursive flag + if [[ "$option_recursive" == "true" ]]; then + vbm "DEBUG:option_recursive:$option_recursive"; + while read -r line; do + file_list+=("$line"); + vbm "DEBUG:added to file_list:$line"; + done < <(find "$item" -type f); + else + while read -r line; do + file_list+=("$line"); + vbm "DEBUG:added to file_list:$line"; + done < <(find "$item" -maxdepth 1 -type f); + fi; + else + die "ERROR:Not a file or dir:item:$item"; + fi; + done; + if [[ $opVerbose == "true" ]]; then + vbm "DEBUG:file_list:"; + printf "%s\n" "${file_list[@]}"; + fi; + + # Prune file_list + for item in "${file_list[@]}"; do + if ! [[ $option_include_dotfiles == "true" ]]; then + ## Ignore files located beneath a dotfile directory (e.g. '/home/my_repo/.git/config') + unset flag_contains_dotfile_parent; + while read -r line; do + ### Check line from output of get_parent_dirnames + pattern="^\."; + if [[ $line =~ $pattern ]]; then + #### line starts with '.' + vbm "DEBUG:Dotfile parent detected. Not including in file_list_pruned:$item"; + vbm "DEBUG:Dotfile in path:item:$item"; + vbm "DEBUG:Dotfile parent:line:$line"; + flag_contains_dotfile_parent="true"; + break + fi; + done < <(get_parent_dirnames "$item"); + if [[ $flag_contains_dotfile_parent == "true" ]]; then + unset flag_contains_dotfile_parent; + continue; # skip to next item (i.e. don't add to file_list_pruned) + fi; + + ## Ignore dotfiles themselves + item_basename="$(basename "$item")"; + pattern="^\."; + if [[ $item_basename =~ $pattern ]]; then + vbm "INFO :Skipping dotfile:item:$item"; + continue; # skip to next item + fi; + fi; + + ## Ignore files with newlines present in filename. See [2]. + if [[ $item =~ $'\n' ]]; then + yell "INFO :Skipping file name with newline:$item"; + continue; # skip to next item + fi; + + ## Ignore files that end in '~'. + if [[ $item =~ ~$ ]]; then + yell "INFO :Skipping file ending in tilde:$item"; + continue; # skip to next item + fi; + + ## Add item to file_list_pruned + file_list_pruned+=("$item"); + done; + if [[ $opVerbose == "true" ]]; then + vbm "DEBUG:file_list_pruned:"; + printf "%s\n" "${file_list_pruned[@]}"; + fi; + + # Decide what actions to take for items in file_list_pruned + for item in "${file_list_pruned[@]}"; do + vbm "DEBUG:considering action to take for item:$item"; + unset path_src path_prf dir_parent dir_source; + + ## Check file extension + if [[ $item =~ .ots$ ]]; then + ### item ends in '.ots'. Item is proof file. + vbm "DEBUG:item ends in '.ots'. Item is proof file:item:$item"; + if [[ -f ${item%.ots} ]]; then + #### Proof file (item) is adjacent to source file + vbm "DEBUG:Proof file (item) is adjacent to source file."; + ##### Upgrade and verify proof file against adjacent source file + vbm "DEBUG:Marking proof file to be upgraded and verified."; + path_src="${item%.ots}"; + path_prf="$item"; + files_to_upgrade+=("$(printf "%s" "$path_prf")"); + files_to_verify+=("$(printf "%s\n%s" "$path_src" "$path_prf")"); + else + #### Proof file (item) is not adjacent to source file + vbm "DEBUG:Proof file (item) is not adjacent to source file."; + #### Check if source file in parent dir + dir_parent="$(dirname "$(dirname "$item")" )"; + cand_src_filename="$(basename "$item")"; + cand_src_path="$dir_parent/$cand_src_filename"; + if [[ -f "$cand_src_path" ]]; then + ##### source file in parent dir + vbm "DEBUG:found source file in parent:cand_src_path:$cand_src_path"; + path_src="$cand_src_path"; + path_prf="$item"; + files_to_upgrade+=("$(printf "%s" "$path_prf")"); + files_to_verify+=("$(printf "%s\n%s" "$path_src" "$path_prf")"); + else + #### Throw non-fatal error + vbm "DEBUG:Source file not found for proof file:item:$item"; + yell "ERROR:Item is proof file but source filei not adjacent in parent dir. item:$item"; + #### Attempt upgrade only + vbm "DEBUG:Marking proof file to be upgraded."; + path_prf="$item"; + files_to_upgrade+=("$(printf "%s" "$path_prf")"); + fi; + fi; + else + ### item does not end in '.ots'. Item is source file. + vbm "DEBUG:item does NOT end in '.ots'. Item is source file."; + if [[ -f "$item".ots ]]; then + #### Proof file is adjacent to source file (item). + vbm "DEBUG:Proof file is adjacent to source file (item)."; + ##### Upgrade and verify proof file against adjacent source file. + vbm "DEBUG:Marking proof file to be upgraded and verified."; + path_src="$item"; + path_prf="$item.ots"; + files_to_upgrade+=("$(printf "%s" "$path_prf")"); + files_to_verify+=("$(printf "%s\n%s" "$path_src" "$path_prf")"); + else + #### Proof file is not adjacent to source file (item). + #### Check if proof file is in subdir + vbm "DEBUG:checking if proof file for source file (item) is in subdir:item:$item"; + unset flag_proof_in_subdir; + dir_item="$(dirname "$item")"; + cand_prf_filename="$(basename "$item")".ots; + while read -r line; do + line_basename="$(basename "$line")"; + if [[ $line_basename == "$cand_prf_filename" ]]; then + flag_proof_in_subdir="true"; + path_prf="$line"; + vbm "DEBUG:proof found in subdir at:line:$line"; + break; + fi; + done < <(find "$dir_item" -mindepth 2 -maxdepth 2 -type f) + if [[ $flag_proof_in_subdir == "true" ]]; then + ##### Proof file is in subdir + vbm "DEBUG:Proof file detected in subdir relative to source file (item)"; + #path_prf="$path_prf"; # set in while loop + path_src="$item"; + files_to_upgrade+=("$(printf "%s" "$path_prf")"); + files_to_verify+=("$(printf "%s\n%s" "$path_src" "$path_prf")"); + else + ##### Proof file is not in subdir + vbm "DEBUG:Proof file not detected in subdir relative to source file (item)."; + #### Stamp source file + vbm "DEBUG:Marking source file to be stamped."; + path_src="$item"; + files_to_stamp+=("$(printf "%s" "$path_src")") + fi; + unset flag_proof_in_subdir; + fi; + fi; + done; + unset path_src path_prf dir_item dir_parent cand_prf_filename cand_src_filename line_basename cand_src_path + + # Prune action lists. + ## Sort and prune file action arrays + ### files to upgrade + while read -r -d $'\0' line; do + vbm "DEBUG:adding to files_to_upgrade_pruned:line:$line"; + files_to_upgrade_pruned+=("$line"); + done < <(printf "%s\0" "${files_to_upgrade[@]}" | sort -zu | shuf -z); # See [1] + if [[ $opVerbose == "true" ]]; then + vbm "DEBUG:files_to_upgrade_pruned:"; + printf "%s\n" "${files_to_upgrade_pruned[@]}"; + fi; + + ### files to verify + while read -r -d $'\0' line; do + vbm "DEBUG:adding to files_to_verify_pruned:line:$line"; + files_to_verify_pruned+=("$line"); + done < <(printf "%s\0" "${files_to_verify[@]}" | sort -zu | shuf -z); # See [1] + if [[ $opVerbose == "true" ]]; then + vbm "DEBUG:files_to_verify_pruned:"; + printf "%s\n\n" "${files_to_verify_pruned[@]}"; + fi; + + ### files to stamp + while read -r -d $'\0' line; do + vbm "DEBUG:adding to files_to_stamp_pruned:line:$line"; + files_to_stamp_pruned+=("$line"); + done < <(printf "%s\0" "${files_to_stamp[@]}" | sort -zu | shuf -z); # See [1] + if [[ $opVerbose == "true" ]]; then + vbm "DEBUG:files_to_stamp_pruned:"; + printf "%s\n" "${files_to_stamp_pruned[@]}"; + fi; + + # Act on files + ## Upgrade files + for item in "${files_to_upgrade_pruned[@]}"; do + path_prf="$(cut -d $'\n' -f1 < <(echo "$item"))"; + if [[ -z "$path_prf" ]]; then + yell "ERROR:blank upgrade item encountered. Skipping:item:$item"; + continue; + fi; + vbm "DEBUG:Attempting to upgrade proof file:path_prf:$path_prf"; + if [[ ! $option_dry_run == "true" ]]; then + ots upgrade "$path_prf"; + else + yell "DEBUG:DRY RUN:Not running:\"ots upgrade $path_prf\""; + fi; + + done; + + ## Verify files + for item in "${files_to_verify_pruned[@]}"; do + path_src="$(cut -d $'\n' -f1 < <(echo "$item"))"; + path_prf="$(cut -d $'\n' -f2 < <(echo "$item"))"; + if [[ -z "$path_src" ]] || [[ -z "$path_prf" ]]; then + yell "ERROR:blank verify item encountered. Skipping:item:$item"; + continue; + fi; + vbm "DEBUG:Attempting to verify source file:path_src:$path_src"; + vbm "DEBUG: against proof file: path_prf:$path_prf"; + if [[ ! $option_dry_run == "true" ]]; then + ots verify -f "$path_src" "$path_prf"; + else + yell "DEBUG:DRY RUN:Not running:\"ots verify -f $path_src $path_prf\""; + fi; + + done; + + ## Stamp files + for item in "${files_to_stamp_pruned[@]}"; do + path_src="$(cut -d $'\n' -f1 < <(echo "$item"))"; + if [[ -z "$path_src" ]]; then + yell "ERROR:blank stamp item encountered. Skipping:item:$item"; + continue; + fi; + vbm "DEBUG:Attempting to stamp source file:path_src:$path_src"; + if [[ ! $option_dry_run == "true" ]]; then + ots stamp "$item"; + else + yell "DEBUG:DRY RUN:Not running:\"ots stamp $item\""; + fi; + + done; + +}; # main program + +# Run program +main "$@"; -- 2.30.2