2020-07-25 23:39:09 +00:00
|
|
|
#!/usr/bin/env bash
|
2019-07-03 21:08:59 +00:00
|
|
|
|
2019-12-31 05:38:46 +00:00
|
|
|
# Requires the printing.sh helper to be sourced.
|
|
|
|
# Requires the platform.sh helper to be sourced.
|
2019-07-03 21:08:59 +00:00
|
|
|
|
|
|
|
#---------------------------------------------------------------------------------------------------
|
|
|
|
# API
|
|
|
|
#---------------------------------------------------------------------------------------------------
|
|
|
|
|
2019-12-31 05:38:46 +00:00
|
|
|
|
2021-02-07 20:11:28 +00:00
|
|
|
# Will return a symlink path in its expanded form. If the path's root is the
|
2019-12-31 05:38:46 +00:00
|
|
|
# home directory symbol "~" then it'll be replaced by the full home path.
|
2019-07-03 21:08:59 +00:00
|
|
|
expand_path() {
|
2020-07-26 17:58:29 +00:00
|
|
|
local ret="$1"
|
|
|
|
|
|
|
|
IFS="/" read -ra parts <<< "$ret"
|
|
|
|
if [[ "${parts[0]}" == "~" ]]; then
|
|
|
|
ret="$HOME"
|
|
|
|
for ((i=1; i < ${#parts[@]}; i++))
|
|
|
|
do
|
|
|
|
ret="$ret/${parts[$i]}"
|
|
|
|
done
|
|
|
|
fi
|
|
|
|
ret=$(readlink -m "$ret")
|
|
|
|
echo $ret
|
2019-07-03 21:08:59 +00:00
|
|
|
}
|
|
|
|
|
2021-02-07 20:11:28 +00:00
|
|
|
# Returned value does not have a trailing '\'.
|
2019-12-31 05:38:46 +00:00
|
|
|
unix_to_windows_path() {
|
2021-02-07 20:11:28 +00:00
|
|
|
ret="$1"
|
|
|
|
if [[ $(is_windows_path "$ret") -eq 0 ]]; then
|
|
|
|
if [[ $(is_absolute_unix_path "$ret") -eq 1 ]]; then
|
2019-12-31 05:38:46 +00:00
|
|
|
ret="${ret/\//}"
|
|
|
|
# Fix the drive name, e.g. c\foo becomes c:\foo
|
|
|
|
ret=$(sed 's,\([a-zA-Z]*\),\1:,' <<< "$ret")
|
|
|
|
fi
|
2020-12-21 04:43:32 +00:00
|
|
|
ret="${ret////\\}" # Replace Unix slashes.
|
|
|
|
ret="${ret//\\\(/\(}" # Remove backslash before (.
|
|
|
|
ret="${ret//\\\)/\)}" # Remove backslash before ).
|
2019-12-31 05:38:46 +00:00
|
|
|
fi
|
2021-02-07 20:11:28 +00:00
|
|
|
|
|
|
|
# Strip trailing slashes.
|
|
|
|
shopt -s extglob
|
|
|
|
ret=$(echo "${ret%%+(\\)}")
|
|
|
|
|
|
|
|
echo $ret
|
2019-07-03 21:08:59 +00:00
|
|
|
}
|
|
|
|
|
2021-02-07 20:11:28 +00:00
|
|
|
# Returned value does not have a trailing '/'.
|
2019-07-03 21:08:59 +00:00
|
|
|
windows_to_unix_path() {
|
2021-02-07 20:11:28 +00:00
|
|
|
ret="$1"
|
2020-07-26 17:58:29 +00:00
|
|
|
ret="/${ret/:/}" # Remove drive ':'.
|
|
|
|
ret="${ret//\\//}" # Replace Windows slashes.
|
|
|
|
ret="${ret// /\\ }" # Add a backslash before spaces.
|
2020-12-21 04:43:32 +00:00
|
|
|
ret="${ret//\(/\\(}" # Add a backslash before (.
|
|
|
|
ret="${ret//\)/\\)}" # Add a backslash before ).
|
2021-02-07 20:11:28 +00:00
|
|
|
|
|
|
|
# If the passed in path was a unix path then we'll have two leading '/'; strip if it exists.
|
|
|
|
ret="${ret/\/\//\/}"
|
|
|
|
|
|
|
|
# Strip trailing slashes.
|
|
|
|
shopt -s extglob
|
|
|
|
ret=$(echo "${ret%%+(/)}")
|
|
|
|
|
|
|
|
echo "$ret"
|
|
|
|
}
|
|
|
|
|
|
|
|
# Returns a Unix path without escaped spaces, e.g. "/x/some folder" instead of "/x/some\ folder"
|
|
|
|
windows_to_unix_path_unescaped() {
|
|
|
|
ret=$(windows_to_unix_path "$1")
|
|
|
|
ret="${ret/\\ / }" # Remove '\' that appears before spaces.
|
|
|
|
echo "$ret"
|
|
|
|
}
|
|
|
|
|
|
|
|
# Returns a Unix path with spaces escaped with a '\'.
|
|
|
|
escape_unix_path() {
|
|
|
|
ret="$1"
|
|
|
|
ret="${ret/ /\\ }"
|
2020-07-26 17:58:29 +00:00
|
|
|
echo "$ret"
|
2019-07-03 21:08:59 +00:00
|
|
|
}
|
|
|
|
|
2021-02-07 20:11:28 +00:00
|
|
|
strip_path() {
|
|
|
|
local result=$(basename "${1}")
|
|
|
|
echo "$result"
|
|
|
|
}
|
|
|
|
|
|
|
|
strip_filename() {
|
|
|
|
local result=$(dirname "${1}")
|
|
|
|
echo "$result"
|
|
|
|
}
|
|
|
|
|
2019-07-03 21:08:59 +00:00
|
|
|
move_file() {
|
2020-07-26 17:58:29 +00:00
|
|
|
local src="$1"
|
2021-02-07 20:11:28 +00:00
|
|
|
local src_expanded=$(expand_path "$src")
|
|
|
|
|
|
|
|
local dest_path=$(windows_to_unix_path_unescaped "$2")
|
|
|
|
local dest_filename="$3"
|
2020-07-26 17:58:29 +00:00
|
|
|
|
2021-02-07 20:11:28 +00:00
|
|
|
if [[ $dest_filename == "" ]]; then
|
|
|
|
dest_filename=$(strip_path "$src")
|
2020-07-26 17:58:29 +00:00
|
|
|
fi
|
|
|
|
|
2021-02-07 20:11:28 +00:00
|
|
|
if [[ -e "$src_expanded" ]]; then
|
|
|
|
mkdir -p "$dest_path"
|
|
|
|
|
|
|
|
local dest="$dest_path/$dest_filename"
|
|
|
|
mv "$src_expanded" "$dest"
|
|
|
|
printf "${BOLD}${GREEN}==> ${NORMAL}Moved ${BOLD}${YELLOW}'$src'${NORMAL} to ${BOLD}${YELLOW}'$dest'${NORMAL}\n" 2>/dev/null
|
2020-07-26 17:58:29 +00:00
|
|
|
else
|
2021-02-07 20:11:28 +00:00
|
|
|
error "Unable to find $src_expanded!\n"
|
2020-07-26 17:58:29 +00:00
|
|
|
fi
|
2019-07-03 21:08:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
copy_file() {
|
2020-07-26 17:58:29 +00:00
|
|
|
local src="$1"
|
2021-02-07 20:11:28 +00:00
|
|
|
local src_expanded=$(expand_path "$src")
|
2020-07-26 17:58:29 +00:00
|
|
|
|
2021-02-07 20:11:28 +00:00
|
|
|
local dest_path=$(windows_to_unix_path_unescaped "$2")
|
|
|
|
local dest_filename="$3"
|
|
|
|
|
|
|
|
if [[ $dest_filename == "" ]]; then
|
|
|
|
dest_filename=$(strip_path "$src_expanded")
|
2020-07-26 17:58:29 +00:00
|
|
|
fi
|
|
|
|
|
2021-02-07 20:11:28 +00:00
|
|
|
if [[ -e "$src_expanded" ]]; then
|
|
|
|
mkdir -p "$dest_path"
|
|
|
|
|
|
|
|
local dest="$dest_path/$dest_filename"
|
|
|
|
cp "$src_expanded" "$dest"
|
|
|
|
printf "${BOLD}${GREEN}==> ${NORMAL}Copied ${BOLD}${YELLOW}'$src'${NORMAL} to ${BOLD}${YELLOW}'$dest'${NORMAL}\n" 2>/dev/null
|
2020-07-26 17:58:29 +00:00
|
|
|
else
|
2021-02-07 20:11:28 +00:00
|
|
|
error "Unable to find $src_expanded!\n"
|
2020-07-26 17:58:29 +00:00
|
|
|
fi
|
2019-07-03 21:08:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
copy_dir_files() {
|
2021-02-07 20:11:28 +00:00
|
|
|
local src=$(expand_path "$1")
|
|
|
|
local src_expanded=$(expand_path "$src")
|
|
|
|
|
|
|
|
local dest_path=$(windows_to_unix_path_unescaped "$2")
|
|
|
|
|
|
|
|
if [[ -d $src_expanded ]]; then
|
|
|
|
mkdir -p $dest_path
|
|
|
|
|
|
|
|
# Need to escape in order to use the wildcard and we have to eval in order to retain the backslash.
|
|
|
|
local src_escaped=$(escape_unix_path "$src_expanded")
|
|
|
|
cmd="cp -r $src_escaped/* \"$dest_path\""
|
|
|
|
eval $cmd
|
2020-07-26 17:58:29 +00:00
|
|
|
|
2021-02-07 20:11:28 +00:00
|
|
|
printf "${BOLD}${GREEN}==> ${NORMAL}Copied contents of ${BOLD}${YELLOW}'$src'${NORMAL} into ${BOLD}${YELLOW}'$dest_path'${NORMAL}\n" 2>/dev/null
|
2020-07-26 17:58:29 +00:00
|
|
|
else
|
2021-02-07 20:11:28 +00:00
|
|
|
error "Unable to find $src_expanded!\n"
|
2020-07-26 17:58:29 +00:00
|
|
|
fi
|
2019-07-03 21:08:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
is_absolute_unix_path() {
|
2020-07-26 17:58:29 +00:00
|
|
|
if [[ $1 =~ ^/ ]]; then echo 1; else echo 0; fi
|
2019-07-03 21:08:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
is_sym_file() {
|
2020-07-26 17:58:29 +00:00
|
|
|
if [[ $1 =~ ^\.{1} ]]; then echo 1; else echo 0; fi
|
2019-07-03 21:08:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
is_windows_path() {
|
2020-07-26 17:58:29 +00:00
|
|
|
if [[ ! $1 =~ \/+ ]]; then echo 1; else echo 0; fi
|
2019-07-03 21:08:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
is_unix_path() {
|
2020-07-26 17:58:29 +00:00
|
|
|
echo $(! is_windows_path "$1")
|
2019-07-03 21:08:59 +00:00
|
|
|
}
|
2019-12-31 05:38:46 +00:00
|
|
|
|
|
|
|
path_has_a_space() {
|
|
|
|
regexp="[[:blank:]]+"
|
|
|
|
if [[ $1 =~ $regexp ]]; then echo 1; else echo 0; fi
|
|
|
|
}
|
|
|
|
|
|
|
|
# Expands a path when it's not a symbolic link or an absolute drive path.
|
2021-02-07 20:11:28 +00:00
|
|
|
clean_link_file_path() {
|
2019-12-31 05:38:46 +00:00
|
|
|
path=$1
|
|
|
|
if [[ $(is_absolute_unix_path "$path") -eq 0 && $(is_sym_file "$path") -eq 0 ]]; then
|
|
|
|
path=$(expand_path "$path")
|
|
|
|
fi
|
|
|
|
echo $path
|
|
|
|
}
|
|
|
|
|
|
|
|
# Creates a symlink.
|
|
|
|
# Requires an admin shell when running under Windows.
|
|
|
|
link_file() {
|
|
|
|
source_path=$1
|
|
|
|
dest_path=$2
|
|
|
|
require_confirmation=$3
|
|
|
|
expand_symlinks=$4
|
2020-09-30 01:51:11 +00:00
|
|
|
debug=0
|
2019-12-31 05:38:46 +00:00
|
|
|
|
|
|
|
os_is_windows is_windows
|
|
|
|
os_is_unix is_unix
|
|
|
|
|
2020-05-08 00:35:08 +00:00
|
|
|
# @INSTEAD ESCAPE THE SPACES IN THE FINAL WINDOWS PATH:
|
|
|
|
# e.g. path="${path// /\\ }" # Add a backslash before spaces.
|
|
|
|
# https://stackoverflow.com/questions/1473981/how-to-check-if-a-string-has-spaces-in-bash-shell
|
|
|
|
# https://stackoverflow.com/questions/28256178/how-can-i-match-spaces-with-a-regexp-in-bash
|
2019-12-31 05:38:46 +00:00
|
|
|
|
|
|
|
source_has_space=$(path_has_a_space "$source_path")
|
|
|
|
dest_has_space=$(path_has_a_space "$dest_path")
|
|
|
|
|
|
|
|
if [[ $debug -eq 1 ]]; then
|
|
|
|
echo source path: $source_path
|
|
|
|
echo dest path: $dest_path
|
|
|
|
echo source has space: $source_has_space
|
|
|
|
echo dest has space: $dest_has_space
|
|
|
|
echo abs unix source: $(is_absolute_unix_path "$source_path")
|
|
|
|
echo abs unix dest: $(is_absolute_unix_path "$dest_path")
|
|
|
|
echo "require_confirmation? $require_confirmation"
|
|
|
|
echo "expand_symlinks? $expand_symlinks"
|
|
|
|
fi
|
|
|
|
|
2020-07-25 23:39:09 +00:00
|
|
|
if [[ $is_windows -eq 1 ]]; then
|
|
|
|
if [[ $expand_symlinks -eq 1 ]]; then
|
|
|
|
source_path=$(expand_path "$source_path")
|
|
|
|
dest_path=$(expand_path "$dest_path")
|
|
|
|
else
|
2021-02-07 20:11:28 +00:00
|
|
|
source_path=$(clean_link_file_path "$source_path")
|
|
|
|
dest_path=$(clean_link_file_path "$dest_path")
|
2020-07-25 23:39:09 +00:00
|
|
|
fi
|
2019-12-31 05:38:46 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
if [[ $debug -eq 1 ]]; then
|
|
|
|
echo "after source: $source_path"
|
|
|
|
echo "after dest: $dest_path"
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Verify that the source path exists.
|
|
|
|
! test -d "$source_path" && ! test -e "$source_path" && error "Source path '$source_path' doesn't exist!" && abort
|
|
|
|
|
|
|
|
# Verify that the dest path doesn't already exist.
|
2020-03-15 18:44:36 +00:00
|
|
|
test -d "$dest_path" && error "Dest folder '$dest_path' already exists!\n" && return
|
|
|
|
test -e "$dest_path" && error "Dest file '$dest_path' already exists!\n" && return
|
2019-12-31 05:38:46 +00:00
|
|
|
|
|
|
|
if [[ $is_windows -eq 1 ]]; then
|
2020-09-30 01:51:11 +00:00
|
|
|
cmd_source_path=$(unix_to_windows_path "$source_path")
|
|
|
|
cmd_dest_path=$(unix_to_windows_path "$dest_path")
|
|
|
|
if [[ $source_has_space -eq 1 ]]; then cmd_source_path="\"$cmd_source_path\""; fi
|
|
|
|
if [[ $dest_has_space -eq 1 ]]; then cmd_dest_path="\"$cmd_dest_path\""; fi
|
|
|
|
link_cmd="cmd //c 'mklink $cmd_dest_path $cmd_source_path'"
|
2019-12-31 05:38:46 +00:00
|
|
|
else
|
2020-09-30 01:51:11 +00:00
|
|
|
if [[ $source_has_space -eq 1 ]]; then cmd_source_path="\"$cmd_source_path\""; fi
|
|
|
|
if [[ $dest_has_space -eq 1 ]]; then cmd_dest_path="\"$cmd_dest_path\""; fi
|
|
|
|
link_cmd="ln -sf $cmd_source_path $cmd_dest_path"
|
2019-12-31 05:38:46 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
if [[ $require_confirmation -eq 1 ]]; then
|
2020-07-26 17:58:29 +00:00
|
|
|
echo "${BOLD}${BLUE}Will attempt to link ${YELLOW}$source_path${BLUE} to ${YELLOW}$dest_path${BLUE}"
|
2019-12-31 05:38:46 +00:00
|
|
|
printf "${BOLD}Enter 1 to proceed\n${YELLOW}> ${NORMAL}"
|
|
|
|
read confirm
|
|
|
|
if [[ $confirm != 1 ]]; then abort; fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [[ $debug -eq 1 ]]; then
|
2020-09-30 01:51:11 +00:00
|
|
|
echo Final cmd source: $cmd_source_path
|
|
|
|
echo Final cmd dest: $cmd_dest_path
|
2019-12-31 05:38:46 +00:00
|
|
|
echo Link cmd:: $link_cmd
|
|
|
|
fi
|
|
|
|
|
2020-08-09 19:25:35 +00:00
|
|
|
printf "${BOLD}${GREEN}==> ${NORMAL}Linking ${BOLD}${YELLOW}'$source_path'${NORMAL} to ${BOLD}${YELLOW}'$dest_path'${NORMAL}\n" 2>/dev/null
|
|
|
|
eval $link_cmd 1>/dev/null
|
2019-12-31 05:38:46 +00:00
|
|
|
}
|
|
|
|
|
2021-02-04 17:18:47 +00:00
|
|
|
setup_file() {
|
2020-05-14 04:36:01 +00:00
|
|
|
src=$1
|
|
|
|
dest=$2
|
|
|
|
if [ ! -f $dest ]; then
|
|
|
|
link_file $src $dest $confirm_link
|
|
|
|
else
|
2020-07-26 17:58:29 +00:00
|
|
|
printf "${BOLD}${MAGENTA}==> ${NORMAL}${BOLD}${YELLOW}'$dest'${NORMAL} already linked to ${BOLD}${YELLOW}'$src'${NORMAL}\n"
|
2020-05-14 04:36:01 +00:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2021-02-04 17:18:47 +00:00
|
|
|
setup_dir() {
|
2020-05-14 04:36:01 +00:00
|
|
|
src=$1
|
|
|
|
dest=$2
|
2021-02-04 17:18:47 +00:00
|
|
|
abort_if_src_not_found=$3
|
|
|
|
|
2020-08-09 19:25:35 +00:00
|
|
|
if [ ! -d $src ]; then
|
|
|
|
error "Source path '$src' doesn't exist!\n"
|
2021-02-04 17:18:47 +00:00
|
|
|
if [[ $abort_if_src_not_found != "1" ]]; then
|
2020-08-09 19:25:35 +00:00
|
|
|
abort
|
|
|
|
else
|
|
|
|
return
|
|
|
|
fi
|
|
|
|
fi
|
2020-05-14 04:36:01 +00:00
|
|
|
if [ ! -d $dest ]; then
|
|
|
|
link_file $src $dest $confirm_link
|
|
|
|
else
|
2020-07-26 17:58:29 +00:00
|
|
|
printf "${BOLD}${MAGENTA}==> ${NORMAL}${BOLD}${YELLOW}'$dest'${NORMAL} already linked to ${BOLD}${YELLOW}'$src'${NORMAL}\n"
|
2020-05-14 04:36:01 +00:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2021-02-04 17:18:47 +00:00
|
|
|
create_dir() {
|
|
|
|
path=$1
|
|
|
|
if [ -d $path ]; then
|
|
|
|
printf "${BOLD}${MAGENTA}==> ${NORMAL}${BOLD}${YELLOW}'$path'${NORMAL} already exists${NORMAL}\n"
|
|
|
|
return
|
|
|
|
fi
|
|
|
|
mkdir $path
|
|
|
|
printf "${BOLD}${GREEN}==> ${NORMAL}Created ${BOLD}${YELLOW}'$path'${NORMAL}\n"
|
|
|
|
}
|
|
|
|
|