2 # Copyright (C) 2014-2016 Ian Kelling
3 # This program is under GPL v. 3 or later, see <http://www.gnu.org/licenses/>
7 lnf -T TARGET LINK_NAME (1st form)
9 lnf TARGET... DIRECTORY (3rd form)
10 Create symlinks forcefully
12 Removes existing files using trash-put or rm -rf if it is not available,
13 or trash-put fails due to a limitation such as a cross-filesystem link.
14 Create directory if needed. Slightly more restrictive arguments than ln.
16 In the 1st form, create a link to TARGET with the name LINK_NAME. In the 2nd
17 form, create a link to TARGET in the current directory. In the 3rd form, create
18 links to each TARGET in DIRECTORY.
20 Do export LNF_VERBOSE=true for verbose output
23 if [[ $1 == --help ||
$1 == -h ||
$# -eq 0 ]]; then
29 if [[ $1 == -T ]]; then
32 if (( $# != 2 )); then
33 echo "lnf error: expected 2 arguments with -T flag. Got $#"
38 local reset_extglob
=false
39 ! shopt extglob
>/dev
/null
&& reset_extglob
=true
43 local x ret prefix dir to_remove
49 if [[ -e $2 ||
-L $2 ]]; then
51 elif [[ ! -d $dir ]]; then
53 if [[ -e $dir ||
-L $dir ]]; then
57 elif (( $# >= 2 )); then
58 if [[ -d ${!#} ]]; then
59 prefix
="${!#}/" # last arg
60 for x
in "${@:1:$(( $# - 1 ))}"; do # all but last arg
61 # Remove 1 or more trailing slashes, using.
63 # remove any leading directory components, add prefix
65 [[ -e "$x" ||
-L "$x" ]] && to_remove
+=("$x")
68 if ! mkdir
-p "${!#}"; then
69 echo "lnf error: failed to make directory ${!#}"
73 elif [[ $# -eq 1 ]]; then
74 [[ -e "${1##*/}" || -L "${1##*/}" ]] && to_remove+=("${1##*/}")
76 if (( ${#to_remove[@]} >= 1 )); then
77 if type -P trash-put
>/dev
/null
; then
78 if [[ $LNF_VERBOSE == true
]]; then
79 echo "lnf: trash-put -- ${to_remove[*]}"
81 trash-put
-- "${to_remove[@]}" || ret
=$?
82 # trash-put will fail to trash a link that goes across filesystems (72),
83 # and for empty files (74)
84 # so revert to rm -rf in that case
85 if [[ $ret == 72 ]]; then
86 echo "$0: using rm -rf to overcome cross filesystem trash-put limitation"
87 rm -rf -- "${to_remove[@]}"
88 elif [[ $ret == 74 ]]; then
89 echo "$0: using rm -rf to overcome empty file & hardlink trash-put limitation"
90 rm -rf -- "${to_remove[@]}"
91 elif [[ $ret && $ret != 0 ]]; then
95 if [[ $LNF_VERBOSE == true
]]; then
96 echo "lnf: rm -rf -- ${to_remove[*]}"
98 rm -rf -- "${to_remove[@]}"
102 $reset_extglob && shopt -u extglob
105 if ! mkdir
-p "$(dirname "$2")"; then
106 echo "lnf error: failed to make directory $(dirname "$2")"