minor doc update
[lnf] / lnf
diff --git a/lnf b/lnf
index 29f137df5f89acaa63075826a3801c2cf5333569..ac5ebcc020d04c0a49999bc2488080a5fbbba675 100755 (executable)
--- a/lnf
+++ b/lnf
@@ -1,5 +1,5 @@
 #!/bin/bash
 #!/bin/bash
-# Copyright (C) 2014 Ian Kelling
+# Copyright (C) 2014-2016 Ian Kelling
 # This program is under GPL v. 3 or later, see <http://www.gnu.org/licenses/>
 
 lnf() {
 # This program is under GPL v. 3 or later, see <http://www.gnu.org/licenses/>
 
 lnf() {
@@ -9,13 +9,14 @@ Usage:
        lnf TARGET                  (2nd form)
        lnf TARGET... DIRECTORY     (3rd form)
 
        lnf TARGET                  (2nd form)
        lnf TARGET... DIRECTORY     (3rd form)
 
-Remove existing file in the using trash-put or rm -rf if it is not available.
+Remove existing file in the using trash-put or rm -rf if it is not available,
+or trash-put fails due to a cross-filesystem link.
 Create directory if needed. Slightly more restrictive arguments than ln.
 
 In the 1st form, create a link to TARGET with the name LINK_NAME.  In the 2nd
 form, create a link to TARGET in the current directory.  In the 3rd form, create
 links to each TARGET in DIRECTORY."
 Create directory if needed. Slightly more restrictive arguments than ln.
 
 In the 1st form, create a link to TARGET with the name LINK_NAME.  In the 2nd
 form, create a link to TARGET in the current directory.  In the 3rd form, create
 links to each TARGET in DIRECTORY."
-    
+
     if [[ $1 == --help || $# -eq 0 ]]; then
         echo "$help"
         return 0
     if [[ $1 == --help || $# -eq 0 ]]; then
         echo "$help"
         return 0
@@ -30,38 +31,36 @@ links to each TARGET in DIRECTORY."
             return 1
         fi
     fi
             return 1
         fi
     fi
-    
+
     local reset_extglob=false
     ! shopt extglob >/dev/null && reset_extglob=true
     shopt -s extglob
 
     local reset_extglob=false
     ! shopt extglob >/dev/null && reset_extglob=true
     shopt -s extglob
 
-    
-    local remove x
-    if type -P trash-put >/dev/null; then
-        remove=trash-put
-    else
-        remove="rm -rf"
-    fi
-    
+
+    local x ret prefix dir to_remove
+    local mkdir=false
+
+    to_remove=()
     if [[ $nodir ]]; then
     if [[ $nodir ]]; then
-        if [[ -e "$2" || -L "$2" ]]; then
-            $remove "$2"
-        elif ! mkdir -p "$(dirname "$2")"; then
-            echo "lnf error: failed to make directory $(dirname "$2")"
-            return 1
+        dir="$(dirname "$2")"
+        if [[ -e $2 || -L $2 ]]; then
+            to_remove+=("$2")
+        elif [[ ! -d $dir ]]; then
+            mkdir=true
+            if [[ -e $dir || -L $dir ]]; then
+                to_remove+=("$dir")
+            fi
         fi
     elif (( $# >= 2 )); then
         if [[ -d ${!#} ]]; then
         fi
     elif (( $# >= 2 )); then
         if [[ -d ${!#} ]]; then
-            local oldcwd=$PWD
-            cd "${!#}" # last arg
+            prefix="${!#}/" # last arg
             for x in "${@:1:$(( $# - 1 ))}"; do # all but last arg
             for x in "${@:1:$(( $# - 1 ))}"; do # all but last arg
-                # remove any trailing slashes, uses extglob
+                # Remove 1 or more trailing slashes, using.
                 x="${x%%+(/)}"
                 x="${x%%+(/)}"
-                # remove any leading directory components
-                x="${x##*/}"
-                [[ -e "$x" || -L "$x" ]] && $remove "$x"
+                # remove any leading directory components, add prefix
+                x="$prefix/${x##*/}"
+                [[ -e "$x" || -L "$x" ]] && to_remove+=("$x")
             done
             done
-            cd "$oldcwd"
         else
             if ! mkdir -p "${!#}"; then
                 echo "lnf error: failed to make directory ${!#}"
         else
             if ! mkdir -p "${!#}"; then
                 echo "lnf error: failed to make directory ${!#}"
@@ -69,10 +68,37 @@ links to each TARGET in DIRECTORY."
             fi
         fi
     elif  [[ $# -eq 1 ]]; then
             fi
         fi
     elif  [[ $# -eq 1 ]]; then
-        [[ -e "${1##*/}" || -L "${1##*/}" ]] && $remove "${1##*/}"
+        [[ -e "${1##*/}" || -L "${1##*/}" ]] && to_remove+=("${1##*/}")
+    fi
+    if (( ${#to_remove[@]} >= 1 )); then
+        if type -P trash-put >/dev/null; then
+            trash-put -- "${to_remove[@]}" || ret=$?
+            # trash-put will fail to trash a link that goes across filesystems (72),
+            # and for empty files (74)
+            # so revert to rm -rf in that case
+            if [[ $ret == 72 ]]; then
+                echo "$0: using rm -rf to overcome cross filesystem trash-put limitation"
+                rm -rf -- "${to_remove[@]}"
+            elif [[ $ret == 74 ]]; then
+                echo "$0: using rm -rf to overcome empty file/dir trash-put limitation"
+                rm -rf -- "${to_remove[@]}"
+            elif [[ $ret && $ret != 0 ]]; then
+                return $x
+            fi
+        else
+            rm -rf -- "${to_remove[@]}"
+        fi
+    fi
+
+    $reset_extglob && shopt -u extglob
+
+    if $mkdir; then
+        if ! mkdir -p "$(dirname "$2")"; then
+            echo "lnf error: failed to make directory $(dirname "$2")"
+            return 1
+        fi
     fi
 
     fi
 
-    $reset_extglob && shopt -u extglob 
     ln -s $nodir -- "$@"
 }
 lnf "$@"
     ln -s $nodir -- "$@"
 }
 lnf "$@"