Sync-DJ.ps1 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. class SourceDirs {
  2. static $MixxxConfig = "$env:USERPROFILE\AppData\Local\Mixxx"
  3. static $Test = "C:\tmp\Test With Spaces"
  4. static $Desktop_ITunes = "$env:USERPROFILE\Music\iTunes\iTunes Media\Music"
  5. static $Music_MixxxConfig = "M:\Config\Mixxx"
  6. static $Music_ITunes = "M:\Music\ITUNES"
  7. static $Music_ZipDJ = "M:\Music\ZipDJ Tracks"
  8. static $Music_Music = "M:\Music"
  9. static $Drive_MixxxConfig = "D:\Config\Mixxx"
  10. static $Drive_ITunes = "D:\Music\ITUNES"
  11. static $Drive_ZipDJ = "D:\Music\ZipDJ Tracks"
  12. static $Drive_Music = "D:\Music"
  13. }
  14. class Choice {
  15. # Text to display in the option selection.
  16. [string] $DisplayName
  17. # Source diretory.
  18. [string] $Source
  19. # Destination directory.
  20. [string] $Dest
  21. # If true, rename the existing folder with a date suffix, then copy
  22. # source files to a new folder at the path.
  23. [boolean] $MakeBackup
  24. # If true, skip re-copying files if only timestamps are different.
  25. [boolean] $IgnoreTimestamps
  26. Choice($displayName, $source, $dest, $makeBackup, $ignoreTimestamps) {
  27. $this.Source = $source
  28. $this.Dest = $dest
  29. $this.DisplayName = $displayName
  30. $this.MakeBackup = $makeBackup
  31. $this.IgnoreTimestamps = $ignoreTimestamps
  32. }
  33. }
  34. $CHOICES = @(
  35. ############
  36. # Mixxx
  37. [Choice]::new(
  38. "Mixxx: Desktop --> Server",
  39. [SourceDirs]::MixxxConfig,
  40. [SourceDirs]::Music_MixxxConfig,
  41. $false, # Make Backup
  42. $false # Ignore Timestamps
  43. ),
  44. [Choice]::new(
  45. "Mixxx: Desktop --> Drive",
  46. [SourceDirs]::MixxxConfig,
  47. [SourceDirs]::Drive_MixxxConfig,
  48. $false, # Make Backup
  49. $false # Ignore Timestamps
  50. ),
  51. [Choice]::new(
  52. "Mixxx: Drive --> Laptop",
  53. [SourceDirs]::Music_MixxxConfig,
  54. [SourceDirs]::MixxxConfig,
  55. $true, # Make Backup
  56. $false # Ignore Timestamps
  57. ),
  58. [Choice]::new(
  59. "Mixxx: Drive --> Desktop",
  60. [SourceDirs]::Drive_MixxxConfig,
  61. [SourceDirs]::MixxxConfig,
  62. $true, # Make Backup
  63. $false # Ignore Timestamps
  64. ),
  65. [Choice]::new(
  66. "Mixxx: Laptop --> Drive",
  67. [SourceDirs]::MixxxConfig,
  68. [SourceDirs]::Music_MixxxConfig,
  69. $false, # Make Backup
  70. $false # Ignore Timestamps
  71. ),
  72. ##########
  73. # iTunes
  74. [Choice]::new(
  75. "iTunes: Desktop --> Server",
  76. [SourceDirs]::Desktop_ITunes,
  77. [SourceDirs]::Music_ITunes,
  78. $false, # Make Backup
  79. $true # Ignore Timestamps
  80. ),
  81. [Choice]::new(
  82. "iTunes: Drive --> Server",
  83. [SourceDirs]::Drive_ITunes,
  84. [SourceDirs]::Music_ITunes,
  85. $false, # Make Backup
  86. $true # Ignore Timestamps
  87. ),
  88. [Choice]::new(
  89. "iTunes: Server --> Desktop",
  90. [SourceDirs]::Music_ITunes,
  91. [SourceDirs]::Desktop_ITunes,
  92. $false, # Make Backup
  93. $true # Ignore Timestamps
  94. ),
  95. ##########
  96. # Music
  97. [Choice]::new(
  98. "Music: Server --> Drive",
  99. [SourceDirs]::Music_Music,
  100. [SourceDirs]::Drive_Music,
  101. $false, # Make Backup
  102. $true # Ignore Timestamps
  103. ),
  104. ##########
  105. # Zip DJ
  106. [Choice]::new(
  107. "ZipDJ: Drive --> Server",
  108. [SourceDirs]::Drive_ZipDJ,
  109. [SourceDirs]::Music_ZipDJ,
  110. $false, # Make Backup
  111. $true # Ignore Timestamps
  112. )
  113. )
  114. # Print the given message preceded by the name of the calling function.
  115. function out($message) {
  116. $caller = (Get-PSCallStack)[1].Command
  117. Write-Host "${caller}: $message"
  118. }
  119. # Print the given message, preceded by the name of the calling function,
  120. # prompt the user to hit a key, and exit.
  121. function fail($message) {
  122. $caller = (Get-PSCallStack)[1].Command
  123. Write-Host "ERROR: ${caller}: $message"
  124. Read-Host -Prompt "Press Enter to exit"
  125. exit -1
  126. }
  127. function pause($message) {
  128. $caller = (Get-PSCallStack)[1].Command
  129. Write-Host "${caller}: $message`n`n"
  130. Read-Host -Prompt "Press Enter to continue, or CTRL+C to exit"
  131. }
  132. function GetModifiedDate($dirPath) {
  133. $dir = Get-Item $dirPath
  134. $date = Get-Date $dir.LastWriteTime
  135. return $date.ToShortDateString()
  136. }
  137. # Rename the specified directory to have a suffix based on the
  138. # last modified time.
  139. function makeDatedBackup($dirPath) {
  140. if (-not(Test-Path $dirPath)) {
  141. # Not an error, but nothing we can do.
  142. out "Directory does no exist: ${dirPath}"
  143. return
  144. }
  145. $modifiedDate = GetModifiedDate($dirPath)
  146. $newPath = "$dirPath-$modifiedDate"
  147. if (Test-Path $newPath) {
  148. $num = 2
  149. $newNewPath = "$newPath-$num"
  150. while (Test-Path $newNewPath) {
  151. $num++
  152. }
  153. out "$newPath already exists. Using $newNewPath"
  154. $newPath = $newNewPath
  155. }
  156. $dirName = [io.path]::GetFileName($newPath)
  157. pause "Moving $dirPath to $dirName"
  158. Move-Item -Path $dirPath -Destination $newPath
  159. }
  160. # Synchronize the contents of two directories.
  161. # -NoBackup: Skip moving the existing destination to a dated backup path.
  162. # -IgnoreTimestamps: Skip re-copying files if only timestamps are different.
  163. function syncDirs {
  164. param (
  165. [string] $Source,
  166. [string] $Destination,
  167. [boolean] $MakeBackup,
  168. [boolean] $IgnoreTimestamps
  169. )
  170. if (($Source.Length -eq 0) -or ($Destination.Length -eq 0)) {
  171. fail "Both Source and Destination need to be specified."
  172. }
  173. if (-not(Test-Path $Source)) {
  174. fail "Source does not exist: $Source"
  175. }
  176. if ($MakeBackup) {
  177. out "Backing up $Destination"
  178. makeDatedBackup $Destination
  179. }
  180. # Docs: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/robocopy
  181. $roboWhat = @("/s", "/copy:DAT", "/dcopy:DAT")
  182. $roboOptions = @("/v", "/j")
  183. $roboExclude = @("/xo", "/xx")
  184. $roboAdditionalExcludes = @()
  185. if ($IgnoreTimestamps) {
  186. $roboAdditionalExcludes = @("/xn")
  187. }
  188. pause "Copying contents of: `n`t${Source}`nTo:`n`t${Destination}"
  189. robocopy $Source $Destination $roboWhat $roboOptions $roboExclude
  190. }
  191. function chooseSyncOption() {
  192. $num = 1
  193. Write-Host "`nPick an option to run:"
  194. ForEach ($o in $CHOICES) {
  195. Write-Host ([string]::Format("{0}) {1}", $num, $o.DisplayName))
  196. $num++
  197. }
  198. Write-Host "`n`n"
  199. Write-Host "Before an event: 1, 2, 6, 9"
  200. Write-Host "During an event: 3"
  201. Write-host "After an event: 5, 7, 8, 10, 4"
  202. $input = Read-Host -Prompt "Enter option number"
  203. $choice = [int]$input
  204. if (($choice -lt 1) -or ($choice -gt $CHOICES.Length + 1)) {
  205. fail 'Invalid choice!'
  206. }
  207. return $CHOICES[$choice-1]
  208. }
  209. function Main() {
  210. [Choice] $option = chooseSyncOption
  211. $option
  212. syncDirs `
  213. -Source $option.Source `
  214. -Destination $option.Dest `
  215. -MakeBackup $option.MakeBackup `
  216. -IgnoreTimestamps $option.IgnoreTimestamps
  217. #syncDirs -Source ([SourceDirs]::MixxxConfig) -Destination ([SourceDirs]::Test) -NoBackup -IgnoreTimestamps
  218. pause ([string]::Format("Done running {0}!", $option.DisplayName))
  219. }
  220. Main