media2import.sh 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #
  2. # This is simple script for importing media files from source (such as memory cards)
  3. # to destination (such as local storage), creating date directories and renaming them by timestamp
  4. # of given file in desired format. Other features of script: integrity check (using sha256sum).
  5. #
  6. #
  7. #
  8. # Author: Anton TETERIN (https://og2k.com)
  9. # Source: https://github.com/InstallAndUse/Graphics
  10. #
  11. # History:
  12. # 2023-05-07 * init /A
  13. # 2023-05-08 + read flags from CLI /A
  14. # 2023-05-16 * moved from rsync to file 'for' itiration /A
  15. # 2023-06-27 * upgrading /A
  16. # 2023-06-28 * path with spaces variables /A
  17. # 2023-06-29 + hash comparison /A
  18. # + removal on successful integrity verification /A
  19. # 2023-06-30 + add note to subdir, if specified /A
  20. #
  21. # TODO
  22. # 2024-02-09 * destination path with spaces in quotes will break execution /A
  23. function ts() {
  24. # change d
  25. ts=$(date)
  26. echo $(date )
  27. }
  28. # default help
  29. usage () {
  30. echo "Usage: $0 -s - source, -d destination, -n note";
  31. exit 1;
  32. }
  33. # TODO: skip files which specified extensions (*.LRV, *.THM)
  34. # TODO: remove files with specififed extensions (*.LRV, *.THM)
  35. # read flags
  36. while getopts s:d:n: flag
  37. do
  38. case "${flag}" in
  39. s) src=${OPTARG};;
  40. d) dst=${OPTARG};;
  41. n) note=${OPTARG};;
  42. ?) usage;;
  43. esac
  44. done
  45. # read source path, by default current path (if not given)
  46. # assuming not recursive, only in-directory files will be imported
  47. if [ -z $src ]; then
  48. read -p "[ $(ts) ]: Source [$(pwd)]: " src
  49. if [ -z ${src} ]; then
  50. src="$(pwd)"
  51. fi
  52. fi
  53. # read destination path, by default current path (if not given)
  54. if [ -z $dst ]; then
  55. read -p "[ $(ts) ]: Destination [$(pwd)]: " dst
  56. if [ -z ${dst} ]; then
  57. dst="$(pwd)"
  58. fi
  59. fi
  60. # read note, by default empty
  61. if [ -z $note ]; then
  62. read -p "[ $(ts) ]: Note: " note
  63. # TODO: warning, if space present.
  64. if [ -z ${note} ]; then
  65. note=""
  66. else
  67. # adding hyphen before note, if it is not empty
  68. note=" - ${note}"
  69. fi
  70. fi
  71. # source and destination can not be the same, exit
  72. if [ ${src} = ${dst} ]; then
  73. echo "[ $(ts) ]: Source and destination are the same, exiting..."
  74. exit 2
  75. fi
  76. echo "[ $(ts) ]: ----- [ Transfer details ] ---------------------------------------------"
  77. # check that source directory exists, otherwise - exit
  78. if [ -d "$src" ]; then
  79. # TODO: src, dst total and free disk space before transfer
  80. files_src_total_amount=0
  81. files_src_total_size=0
  82. for file in "$src"/*; do
  83. file_size="$( stat -f %z "$file" )"
  84. # echo "[ $(ts) ]: file: ${file} adding file_size: $(( $file_size/1024/1024 )) MB."
  85. files_src_total_size=$(( $files_src_total_size+$file_size ))
  86. files_src_total_amount=$(( $files_src_total_amount+1 ))
  87. done
  88. echo "[ $(ts) ]: Source: [${src}]"
  89. # TODO: add nice GB figures (need to use awk or bc)
  90. echo "[ $(ts) ]: Total of $files_src_total_amount src files, total size is $(( $files_src_total_size/1024/1024 )) MB)."
  91. else
  92. echo "[ $(ts) ]: src dir does not exist, exiting..."
  93. exit 2
  94. fi
  95. echo "[ $(ts) ]: Destination: [${dst}]"
  96. echo "[ $(ts) ]: Note: [${note}]"
  97. # confirm
  98. read -p "[ $(ts) ]: Confirm (Y): " confirm
  99. if [ ${confirm} = "Y" ]; then
  100. # echo "[ $(ts) ]: Preparing to transfer..."
  101. # check and create destination directory, if needed
  102. if ! [ -d "$dst" ]; then
  103. read -p "[ $(ts) ]: dst dir does not exist, do you want to create? (Y)" confirm
  104. if [ ${confirm} = "Y" ]; then
  105. # TODO: add correct check if exit code is successful
  106. mkdir -v -p -m 700 "$dst"
  107. echo "[ $(ts) ]: dst dir created."
  108. fi
  109. fi
  110. files_copied_filename=()
  111. files_copied_total_size=0
  112. files_error_filename=()
  113. # itirating files in src
  114. for file in "$src"/*; do
  115. # echo "[ $(ts) ]: src dir: ["$src"]"
  116. filename="$(basename "$file")"
  117. # figure out when is the creation date
  118. file_mdate="$( stat -f %Sm -t %Y-%m-%d "$file" )"
  119. file_size="$( stat -f %z "$file" )"
  120. # appending note, if specified
  121. if [ -z "$note" ]; then
  122. dst_subdir="${file_mdate}"
  123. else
  124. dst_subdir="${file_mdate}${note}"
  125. fi
  126. # create subdirectory for creation date
  127. mkdir -p "$dst"/"$dst_subdir"
  128. # TODO: echo 'show which file is being copied out of total' in the same status line below
  129. echo "[ $(ts) ]: [${filename}], modification date is: ${file_mdate}, ( $(( ${file_size}/1024/1024 )) MB )"
  130. # TODO: linux/BSD check for shasum function, if it does not run properly on linux
  131. # calulating src hash sum
  132. src_hash=$( shasum -a 256 "$file" | cut -d ' ' -f 1)
  133. # echo "[ $(ts) ]: src sha256sum: [${src_hash}]"
  134. # echo "[ $(ts) ]: dst subdir: ["$dst"/"$dst_subdir"]"
  135. # main operation
  136. # echo "[ $(ts) ] copying.."
  137. cp "$file" "$dst"/"$dst_subdir"
  138. # calulating dst hash sum
  139. dst_hash=$( shasum -a 256 "${dst}/${dst_subdir}/${filename}" | cut -d ' ' -f 1)
  140. # echo "[ $(ts) ]: dst sha256sum: [${dst_hash}]"
  141. # if shasum is the same, add to statistics and remove file
  142. if [ ${src_hash} = ${dst_hash} ]; then
  143. # add to files_copied array
  144. files_copied_filename+=("$filename")
  145. files_copied_total_size+=$file_size
  146. # TODO: add summarize sized of copied file ${file_size}
  147. # echo "[ $(ts) ]: src and dst hashes are the same, removing src file"
  148. rm "${file}"
  149. else
  150. echo "[ $(ts) ]: src and dst hashes are different, src file will not be removed."
  151. files_error_filename+=("$file")
  152. fi
  153. # TODO: add original file with fullpath to array:
  154. # files_src[]="${file}]"
  155. # TODO: add copied file with fullpath to array:
  156. # files_dst[]="$dst"/"$dst_subdir"/${filename}
  157. done
  158. # TODO: src, dst total and free disk space before transfer
  159. # TODO: src, dst total and free disk space after copy
  160. # TODO: time taken to transfer
  161. # TODO: avarage transfer speed
  162. # TODO: ! unmount src disk ?
  163. # diskutil unmount /Volumes/empty
  164. # TODO: open latest directory created?
  165. # TODO: output total amount of files and size
  166. # itirate files
  167. # read creation date of file
  168. #dst_subdir="${dst}/${file_creation_date}${note}"
  169. # TODO: list subdirs, that created (in order to see, where to files are transferred)
  170. else
  171. # not confirmed
  172. echo "[ $(ts) ]: Operation is not confirmed."
  173. exit 1
  174. fi