link2home.sh 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #! /bin/bash
  2. # Install files in current directory to $HOME in various ways.
  3. #
  4. # By default, create a directory in $HOME with the same name
  5. # as the current directory, then symlink all files in this
  6. # directory into the target directory
  7. #
  8. # Default directories are:
  9. # base directory - $HOME
  10. # target directory - $HOME/`basename $PWD`
  11. # source directory - $PWD
  12. ##
  13. # Usage: ${PROG} [options]
  14. #
  15. # options
  16. #
  17. # Modify the paths used
  18. #
  19. # -p|--path=PATH use PATH as base directory (defalt $HOME)
  20. # -t|--tobase link/copy files directly to base directory
  21. #
  22. # Modify the copy/link behavior
  23. #
  24. # -l|--linkdir symlink this directory itself to base directory
  25. # -c|--copy copy directory to target directory#
  26. # -r|--remove remove old files
  27. #
  28. # Change debugging and output
  29. #
  30. # -d|--debug debug output
  31. # -v|--verbose verbose output
  32. #
  33. # - create a directory in $HOME with the same name as this directory
  34. # - link all files in this directory in the new directory
  35. # - exclude files listed in .link2home.ignore
  36. set -e -u
  37. # Helper functions
  38. PROG=`basename "$0" | tr -d '\n'`
  39. function info() { echo ${PROG}\: info: "$@" 1>&2; }
  40. function warn() { echo ${PROG}\: warning: "$@" 1>&2; }
  41. function error() { echo ${PROG}\: error: "$@" 1>&2; }
  42. function debug() { [[ -v DEBUG ]] && echo ${PROG}\: debug: "$@" 1>&2 || true ; }
  43. function die() { echo ${PROG}\: fatal: "$@" 1>&2 && exit 1; }
  44. #
  45. # Command line parsing
  46. #
  47. function usage() {
  48. debug "in ${FUNCNAME[0]}"
  49. if [[ "$#" -gt 0 ]]; then
  50. warn $@
  51. fi
  52. cat <<END 1>&2
  53. Usage: ${PROG} [options]
  54. options
  55. -c|--copy copy directory to target directory
  56. -l|--linkdir symlink this directory itself to base directory
  57. -p|--path=PATH use PATH as base directory (defalt $HOME)
  58. -r|--remove remove old files
  59. -t|--tobase link files directly to base directory
  60. -d|--debug debug output
  61. -v|--verbose verbose output
  62. END
  63. exit 1
  64. }
  65. # globals variables
  66. declare -A EXCLUSIONS
  67. # parse global options
  68. for i in "$@"
  69. do
  70. case $i in
  71. -d|--debug)
  72. DEBUG=1
  73. d_flag="-d"
  74. shift # past argument with no value
  75. ;;
  76. -c|--copy)
  77. COPYDIR=1
  78. d_flag="-d"
  79. shift # past argument with no value
  80. ;;
  81. -l|--linkdir)
  82. LINKDIR=1
  83. d_flag="-d"
  84. shift # past argument with no value
  85. ;;
  86. -p=*|--PATH=*)
  87. TOPATH=1
  88. TO_PATH="${i#*=}"
  89. p_flag="-d"
  90. shift # past argument=value
  91. ;;
  92. -r|--remove)
  93. REMOVE=1
  94. # remove old files
  95. shift # past argument with no value
  96. ;;
  97. -t|--tobase)
  98. TOBASE=1
  99. d_flag="-d"
  100. shift # past argument with no value
  101. ;;
  102. -v|--verbose)
  103. VERBOSE=1
  104. v_flag="-v"
  105. shift # past argument with no value
  106. ;;
  107. -*|--*)
  108. usage "Unknown state option: $i"
  109. ;;
  110. esac
  111. done
  112. # Pull off command line args
  113. if [ "$#" -ge 1 ]; then
  114. usage "No arguments expected"
  115. fi
  116. # Get abolute path to directory of current file
  117. #REALDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
  118. # use current directory
  119. WHERE_AM_I=`pwd`
  120. # Extract the directory name of this file
  121. CURRENT_BASEDIR=`basename $WHERE_AM_I`
  122. # Determine which directory to use as "HOME"
  123. BASEDIR="${HOME}"
  124. if [[ -v TOPATH ]]; then
  125. BASEDIR="${TO_PATH}"
  126. fi
  127. # Determine final destinaiton dir
  128. if [[ -v TOBASE ]]; then
  129. FINAL_DIR="${BASEDIR}"
  130. else
  131. FINAL_DIR="${BASEDIR}/${CURRENT_BASEDIR}"
  132. fi
  133. # if copying, just do it and stop
  134. if [[ -v COPYDIR ]]; then
  135. [[ -v DEBUG ]] && echo cp -r -p ${WHERE_AM_I} ${FINAL_DIR}
  136. cp -r -p ${WHERE_AM_I} ${FINAL_DIR}
  137. exit 0
  138. fi
  139. # Link this directory into FINAL_DIR
  140. if [[ -v LINKDIR ]]; then
  141. if [ -v REMOVE ]; then
  142. # never remove HOME !!!
  143. if [[ "${HOME}" == "${FINAL_DIR}" ]]; then
  144. [[ -v VERBOSE ]] && info not removing "${HOME}"
  145. else
  146. rm -f "${FINAL_DIR}"
  147. [[ -v VERBOSE ]] && info rm -f "${FINAL_DIR}"
  148. fi
  149. fi
  150. [[ -v VERBOSE ]] && info ln -s "${WHERE_AM_I}" "${FINAL_DIR}"
  151. ln -s "${WHERE_AM_I}" "${FINAL_DIR}" || warn "Unable to link ${WHERE_AM_I}"
  152. exit 0
  153. else
  154. # crate the directory name in $HOME if DNE
  155. mkdir -p "${FINAL_DIR}"
  156. fi
  157. #
  158. # Everything from here is releative to source directory
  159. #
  160. cd "${WHERE_AM_I}"
  161. #
  162. # Ignore files listed in .link2home.ignore
  163. #
  164. if [ -f '.link2home.ignore' ]; then
  165. for exclude in `cat .link2home.ignore`; do
  166. EXCLUSIONS["${exclude}"]="${exclude}"
  167. done
  168. fi
  169. #
  170. # symlink everything here to $HOME
  171. #
  172. debug linking files
  173. #for file in * .[a-z]*; do
  174. for file in * .[a-z0-9A-Z_\-]*; do
  175. SOURCE="${WHERE_AM_I}/${file}"
  176. TARGET="${FINAL_DIR}/${file}"
  177. [ -e "${file}" ] || continue
  178. if [ ${EXCLUSIONS["${file}"]+DNE} ]; then
  179. info skiping "${file}"
  180. else
  181. if [ -v REMOVE ]; then
  182. [[ -v VERBOSE ]] && info rm -f "${FINAL_DIR}/${file}"
  183. rm -f "${FINAL_DIR}/${file}"
  184. fi
  185. if [ -h "${TARGET}" ]; then
  186. [[ -v VERBOSE ]] && info "${TARGET}" already exists. Skipping.
  187. else
  188. [[ -v VERBOSE ]] && info ln -s "${SOURCE}" "${FINAL_DIR}"
  189. ln -s "${SOURCE}" "${FINAL_DIR}" || warn "Unable to link ${SOURCE}"
  190. fi
  191. fi
  192. done