feat(user/bkots): Don't timestamp files changed in last 1 min
[BK-2020-03.git] / user / bkots
old mode 100644 (file)
new mode 100755 (executable)
index 6627d9d..79c6692
@@ -11,6 +11,7 @@ calendars+=("https://finney.calendar.eternitywall.com");
 calendars+=("https://btc.calendar.catallaxy.com");
 calendars+=("https://alice.btc.calendar.opentimestamps.org");
 calendars+=("https://bob.btc.calendar.opentimestamps.org");
 calendars+=("https://btc.calendar.catallaxy.com");
 calendars+=("https://alice.btc.calendar.opentimestamps.org");
 calendars+=("https://bob.btc.calendar.opentimestamps.org");
+age_threshold="60"; # min age to add file; seconds;
 
 # Declare functions
 yell() { echo "$0: $*" >&2; } # print script path and all args to stderr
 
 # Declare functions
 yell() { echo "$0: $*" >&2; } # print script path and all args to stderr
@@ -199,7 +200,7 @@ showVersion() {
     vbm "DEBUG:showVersion function called."
 
     cat <<'EOF'
     vbm "DEBUG:showVersion function called."
 
     cat <<'EOF'
-bkots 0.0.6
+bkots 0.0.9
 Copyright (C) 2022 Steven Baltakatei Sandoval
 License GPLv3: GNU GPL version 3
 This is free software; you are free to change and redistribute it.
 Copyright (C) 2022 Steven Baltakatei Sandoval
 License GPLv3: GNU GPL version 3
 This is free software; you are free to change and redistribute it.
@@ -260,6 +261,8 @@ showUsage() {
         themselves are also ignored by default
         (e.g. '/home/user/.gitconfig').
 
         themselves are also ignored by default
         (e.g. '/home/user/.gitconfig').
 
+        Files modified less than 1 minute ago are ignored.
+
     EXAMPLES:
       bkots -v foo.txt
       bkots foo.txt bar.pdf /home/username/Pictures/
     EXAMPLES:
       bkots -v foo.txt
       bkots foo.txt bar.pdf /home/username/Pictures/
@@ -357,12 +360,15 @@ main() {
     #     - 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 "$@";
     #     - 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)
+    # Input: arrayPosArgs   array with positional arguments
+    #        pathDirOut1    path for output `.ots` files (if pathDirOut1 is specified and is a path)
+    #        age_threshold  var: mininum age in seconds to timestamp file
+    
     # 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
     # 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
+    #             [3] Get mtime of specific file using Bash? https://stackoverflow.com/a/4774377
     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
     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
@@ -376,17 +382,13 @@ main() {
         die "FATAL:Missing dependencies.";
     fi;
     
         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";
+    # Check arguments
+    for arg in "${arrayPosArgs[@]}"; do
+        arg="$(readlink -f "$arg")";
+        if ! { [[ -d $arg ]] || [[ -f $arg ]]; }; then
+            die "FATAL:Not a file or dir:arg:$arg";
         fi;
         fi;
-    fi;
+    done;
 
     # Display ots details
     vbm "$(type ots)"; # show how 'ots' is defined
 
     # Display ots details
     vbm "$(type ots)"; # show how 'ots' is defined
@@ -425,7 +427,7 @@ main() {
                 done < <(find "$item" -maxdepth 1 -type f);
             fi;
         else
                 done < <(find "$item" -maxdepth 1 -type f);
             fi;
         else
-            die "ERROR:Not a file or dir:item:$item";
+            die "FATAL:Not a file or dir:item:$item";
         fi;
     done;
     if [[ $opVerbose == "true" ]]; then
         fi;
     done;
     if [[ $opVerbose == "true" ]]; then
@@ -435,14 +437,21 @@ main() {
 
     # Prune file_list
     for item in "${file_list[@]}"; do
 
     # Prune file_list
     for item in "${file_list[@]}"; do
+        ## Ignore files that end in '.ots.bak'.
+        if [[ $item =~ '.ots.bak'$ ]]; then
+            yell "INFO :Skipping file ending in '.ots.bak':item:$item";
+            continue; # skip to next item
+        fi;
+
+        ## Ignore dotfiles
         if ! [[ $option_include_dotfiles == "true" ]]; then
         if ! [[ $option_include_dotfiles == "true" ]]; then
-            ## Ignore files located beneath a dotfile directory (e.g. '/home/my_repo/.git/config')
+            ### Ignore files located beneath a dotfile directory (e.g. '/home/my_repo/.git/config')
             unset flag_contains_dotfile_parent;
             while read -r line; do
             unset flag_contains_dotfile_parent;
             while read -r line; do
-                ### Check line from output of get_parent_dirnames
+                #### Check line from output of get_parent_dirnames
                 pattern="^\.";
                 if [[ $line =~ $pattern ]]; then
                 pattern="^\.";
                 if [[ $line =~ $pattern ]]; then
-                    #### line starts with '.'
+                    ##### 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";
                     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";
@@ -455,7 +464,7 @@ main() {
                 continue; # skip to next item (i.e. don't add to file_list_pruned)
             fi;
 
                 continue; # skip to next item (i.e. don't add to file_list_pruned)
             fi;
 
-            ## Ignore dotfiles themselves
+            ### Ignore dotfiles themselves
             item_basename="$(basename "$item")";
             pattern="^\.";
             if [[ $item_basename =~ $pattern ]]; then
             item_basename="$(basename "$item")";
             pattern="^\.";
             if [[ $item_basename =~ $pattern ]]; then
@@ -463,7 +472,7 @@ main() {
                 continue; # skip to next item
             fi;
         fi;
                 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";
         ## Ignore files with newlines present in filename. See [2].
         if [[ $item =~ $'\n' ]]; then
             yell "INFO :Skipping file name with newline:$item";
@@ -476,9 +485,11 @@ main() {
             continue; # skip to next item
         fi;
 
             continue; # skip to next item
         fi;
 
-        ## Ignore files that end in '.ots.bak'.
-        if [[ $item =~ '.ots.bak'$ ]]; then
-            yell "INFO :Skipping file ending in '.ots.bak':item:$item";
+        ## Ignore files modified less than age_threshold. See [3].
+        time_now="$(date +%s)"; # epoch seconds
+        item_age="$(stat -c %Y "$item")"; # age in seconds
+        if [[ $(( time_now - item_age )) -lt "$age_threshold" ]]; then
+            yell "INFO :Skipping file modified less than $age_threshold seconds ago:item:$item";
             continue; # skip to next item
         fi;
         
             continue; # skip to next item
         fi;
         
@@ -665,9 +676,9 @@ main() {
         fi;
         vbm "DEBUG:Attempting to stamp source file:path_src:$path_src";
         if [[ ! $option_dry_run == "true" ]]; then
         fi;
         vbm "DEBUG:Attempting to stamp source file:path_src:$path_src";
         if [[ ! $option_dry_run == "true" ]]; then
-            ots stamp "$item";
+            ots stamp "$path_src";
         else
         else
-            yell "DEBUG:DRY RUN:Not running:\"ots stamp $item\"";
+            yell "DEBUG:DRY RUN:Not running:\"ots stamp $path_src\"";
         fi;
         sleep "$ots_delay";
     done;
         fi;
         sleep "$ots_delay";
     done;