Sync-DJ.ps1 7.1 KB

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