variable scope bug and condition on new file
[tee-unique] / appendu-function
index 7749aa47e7fafa3b29c5b158a149ba7e5995e690..a0fdc5d6e0c1b5b73e25a1dc3d87d4766b655626 100644 (file)
@@ -9,22 +9,17 @@ Append unique.
 
 A LINE_SET is one or more lines. Append LINE_SET to FILE if it does not exist in
 FILE.  If no LINE_SET argument is given, read lines from stdin, and treat each
-as a single LINE_SET. Appended text is output to the terminal.
+as a single LINE_SET. Appended text is output to the terminal. Duplicate
+LINE_SETs are treated the same.
 
-  -s      don't try to use sudo when it would help us read or write the file
-  --      stop processing arguments
-  --help  display this message"
+  --           stop processing arguments
+  [-h|--help]  display this message"
 
-    local readsudo writesudo x strings string
-    local dosudo=true
     
     while true; do
-        if [[ $1 == --help ]]; then
+        if [[ $1 == --help || $1 == -h ]]; then
             echo "$help"
             return
-        elif [[ $1 == -s ]]; then
-            dosudo=false
-            shift
         elif [[ $1 == -- ]]; then
             shift
             break
@@ -42,26 +37,28 @@ as a single LINE_SET. Appended text is output to the terminal.
     local file="$1"
     shift
 
-    local readsudo=false
-    local file_exists=false
+    local new_file=true
     if [[ -e $file ]]; then
-        file_exists=true
-        [[ -r $file ]] || readsudo=true
-        [[ -w $file ]] || writesudo=sudo
+        new_file=false
     else
         local dir="$(dirname "$file")"
-        if [[ -d $dir ]]; then
-            [[ ! -w $dir ]] && writesudo=sudo
-        else
+        if [[ ! -d $dir ]]; then
             echo "appendu error: $dir does not exist"
             return 1
         fi
     fi
-    if ! $dosudo; then
-        readsudo=
-        writesudo=
+    if ! $new_file; then
+        if [[ ! -r $file ]]; then
+            echo "appendu error: cannot read or write $file"
+            return 1
+        fi
+        if [[ ! -w $file ]]; then
+            echo "appendu error: cannot read or write $file"
+            return 1
+        fi            
     fi
-    
+
+    local strings
     if (( $# == 0 )); then
         unset IFS
         while read -r x; do
@@ -71,38 +68,35 @@ as a single LINE_SET. Appended text is output to the terminal.
         strings=( "$@" )
     fi
 
-    if $file_exists; then
+    if $new_file; then
         # fix files with no newline at the end.
-        # the following command won't work right on them.
+        # the following command won't work right on them otherwise.
         # e = run script, $a\ means append following text, but there is none,
         # so sed only does what it always does when it was supposed to modify a file,
         # which is append a newline if there was none.
         sed -ie '$a\' "$file"
-        # this removes any trailing newline in the var, so we add it back on,
-        # because we want a consistent ending to match
-        local file_content
-        if $readsudo; then
-            file_content="$(sudo cat "$file")
-"
-        else
-            file_content="$(<"$file")
-"
-        fi
-        # we aren't using regex because we want to match strings,
-        # but we also want our match to start at the beginning of a line,
-        # or the beginning of the file, and to end at a line ending.
-        # So we do some slick bash to match this.
-        local start="?(*
+        # command substitution removes any trailing newlines, so we have to add
+        # a non-newline ending, we randomly chose "b", then remove it.
+        local content=$(cat "$file"; echo b) content=${content%b}
+    fi
+    
+    # we aren't using regex because we want to match strings,
+    # but we also want our match to start at the beginning of a line,
+    # or the beginning of the file, and to end at a line ending.
+    # So we do some slick bash to match this.
+    local start="?(*
 )"
-        local end="
+    local end="
 *"
-        for string in "${strings[@]}"; do
-            [[ $file_content != $start"$string"$end ]] && $writesudo tee -a "$file"<<<"$string"
-        done
-    else
-        for string in "${strings[@]}"; do
-            $writesudo tee -a "$file"<<<"${strings[@]}"
-        done
-    fi
+    local return_code string return_code
+    for string in "${strings[@]}"; do
+        if $new_file || [[ $content != $start"$string"$end ]]; then
+            if ! tee -a "$file"<<<"$string"; then
+                return_code=$?
+                echo "appendu error: error writing to $file"
+                return $return_code
+            fi
+        fi
+    done
     return 0
 }