sync.sh 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #!/bin/bash
  2. # Ensure the media share is mounted
  3. if ! ~/bin/video/isMediaMounted; then
  4. echo 'Media share not available' 1>&2
  5. exit 1
  6. fi
  7. # Config
  8. if [ -z "${BASE_LOCAL}" ]; then
  9. BASE_LOCAL="`~/bin/video/mediaPath`"
  10. fi
  11. if [ -z "${BASE_REMOTE}" ]; then
  12. BASE_REMOTE="/Volumes/Bitcasa Infinite Drive"
  13. fi
  14. # Command-line arguments
  15. SUB_DIR="${1}"
  16. declare -i NUM_FILES
  17. NUM_FILES=1
  18. if [ -n "${2}" ]; then
  19. NUM_FILES="${2}"
  20. fi
  21. declare -i DELAY_DAYS
  22. DELAY_DAYS=30
  23. if [ -n "${3}" ]; then
  24. DELAY_DAYS="${3}"
  25. fi
  26. # Usage checks
  27. if [ -z "${SUB_DIR}" ] || [ $NUM_FILES -lt 1 ] || [ $DELAY_DAYS -lt 1 ]; then
  28. echo "Usage: `basename "${0}"` sub_directory [num_files] [delay_days]" 1>&2
  29. exit 1
  30. fi
  31. # Bail if the load is high
  32. if ! ~/bin/video/checkLoad.sh; then
  33. exit 0
  34. fi
  35. # Allow usage with absolute local paths
  36. if [ "`echo "${SUB_DIR}" | head -c 1`" == '/' ]; then
  37. SUB_DIR="`echo "${SUB_DIR}" | sed "s%${BASE_LOCAL}/%%"`"
  38. fi
  39. # Sanity checks
  40. if [ ! -d "${BASE_LOCAL}/${SUB_DIR}" ]; then
  41. echo "Invalid local directory: ${BASE_LOCAL}/${SUB_DIR}" 1>&2
  42. exit 1
  43. fi
  44. if [ ! -d "${BASE_REMOTE}" ]; then
  45. echo "Remote drive not mounted" 1>&2
  46. exit 1
  47. fi
  48. # Ensure we can actually write to the remote drive
  49. WC="${BASE_REMOTE}/.write_check"
  50. touch "${WC}" >/dev/null 2>&1
  51. if [ ! -e "${WC}" ]; then
  52. echo "Remote drive not writable" 1>&2
  53. exit 1
  54. fi
  55. rm -f "${WC}" >/dev/null 2>&1
  56. if [ -e "${WC}" ]; then
  57. echo "Remote drive not writable" 1>&2
  58. exit 1
  59. fi
  60. # Create the named subdirectory if it does not exist on the remote drive
  61. if [ ! -d "${BASE_REMOTE}/${SUB_DIR}" ]; then
  62. mkdir -p "${BASE_REMOTE}/${SUB_DIR}"
  63. fi
  64. # Grab and sort the local file list
  65. # Limit files by mtime, but include all directories
  66. TMP_LOCAL="`mktemp -t sync.local.XXXXXXXX`"
  67. TMP_LOCAL2="`mktemp -t sync.local2.XXXXXXXX`"
  68. (cd "${BASE_LOCAL}" && find "${SUB_DIR}" -type f -mtime "+${DELAY_DAYS}d" > "${TMP_LOCAL2}")
  69. (cd "${BASE_LOCAL}" && find "${SUB_DIR}" -type d >> "${TMP_LOCAL2}")
  70. cat "${TMP_LOCAL2}" | sort > "${TMP_LOCAL}"
  71. # Grab and sort the remote file list
  72. TMP_REMOTE="`mktemp -t sync.remote.XXXXXXXX`"
  73. (cd "${BASE_REMOTE}" && find "${SUB_DIR}" | sort > "${TMP_REMOTE}")
  74. # Diff to find the first mis-matched file, then drop out temp files
  75. TMP_DIFF="`mktemp -t sync.diff.XXXXXXXX`"
  76. TMP_DIFF2="`mktemp -t sync.diff2.XXXXXXXX`"
  77. diff -u "${TMP_LOCAL}" "${TMP_REMOTE}" | grep "^[\+\-]${SUB_DIR}" > "${TMP_DIFF2}"
  78. rm -f "${TMP_LOCAL}" "${TMP_LOCAL2}" "${TMP_REMOTE}"
  79. # Filter junk
  80. grep -v '\/\._' "${TMP_DIFF2}" | grep -v '\/\.DS_Store$' | grep -v '\/\.git\/' > "${TMP_DIFF}"
  81. rm -f "${TMP_DIFF2}"
  82. # Limit NUM_FILES to the number of files available
  83. COUNT="`cat "${TMP_DIFF}" | wc -l`"
  84. if [ $NUM_FILES -gt $COUNT ]; then
  85. NUM_FILES=$COUNT
  86. fi
  87. # Loop for NUM_FILES
  88. for (( i=1; i<=${NUM_FILES}; i++ )); do
  89. # Choose the file/directory to sync
  90. FILE="`head -n $i "${TMP_DIFF}" | tail -n 1`"
  91. ACTION="`echo "${FILE}" | head -c 1`"
  92. FILE="`echo "${FILE}" | cut -d "${ACTION}" -f 2-`"
  93. # Construct absolute paths
  94. PATH_LOCAL="${BASE_LOCAL}/${FILE}"
  95. PATH_REMOTE="${BASE_REMOTE}/${FILE}"
  96. # Determine the action (i.e. copy to or delete from remote)
  97. if [ "${ACTION}" == '+' ]; then
  98. if [ -n "${NO_DELETE}" ]; then
  99. # Do nothing
  100. true
  101. elif [ -d "${PATH_REMOTE}" ]; then
  102. echo "Removing directory: ${FILE}"
  103. rmdir "${PATH_REMOTE}"
  104. elif [ -f "${PATH_REMOTE}" ]; then
  105. echo "Deleting file: ${FILE}"
  106. rm "${PATH_REMOTE}"
  107. else
  108. echo "Unable to delete file: ${FILE}" 1>&2
  109. exit 2
  110. fi
  111. elif [ "${ACTION}" == '-' ]; then
  112. # Handle files by type
  113. if [ -h "${PATH_LOCAL}" ]; then
  114. echo "Unable to create symlink: ${FILE}" 1>&2
  115. exit 2
  116. elif [ -d "${PATH_LOCAL}" ]; then
  117. echo "Creating directory: ${FILE}"
  118. mkdir "${PATH_REMOTE}"
  119. elif [ -f "${PATH_LOCAL}" ] && [ -r "${PATH_LOCAL}" ]; then
  120. echo "Copying: ${FILE}"
  121. cp "${BASE_LOCAL}/${FILE}" "${BASE_REMOTE}/${FILE}"
  122. else
  123. echo "Unable to copy file: ${FILE}" 1>&2
  124. exit 2
  125. fi
  126. else
  127. echo "Invalid action: ${ACTION}" 1>&2
  128. exit 2
  129. fi
  130. done
  131. # Cleanup
  132. rm -f "${TMP_DIFF}"
  133. exit 0