| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- class SourceDirs {
- static $MixxxConfig = "$env:USERPROFILE\AppData\Local\Mixxx"
- static $Test = "C:\tmp\Test With Spaces"
- static $Desktop_ITunes = "$env:USERPROFILE\Music\iTunes\iTunes Media\Music"
-
- static $Music_MixxxConfig = "M:\Config\Mixxx"
- static $Music_ITunes = "M:\Music\ITUNES"
- static $Music_ZipDJ = "M:\Music\ZipDJ Tracks"
- static $Music_Music = "M:\Music"
-
- static $Drive_MixxxConfig = "D:\Config\Mixxx"
- static $Drive_ITunes = "D:\Music\ITUNES"
- static $Drive_ZipDJ = "D:\Music\ZipDJ Tracks"
- static $Drive_Music = "D:\Music"
- }
- class Choice {
- # Text to display in the option selection.
- [string] $DisplayName
- # Source diretory.
- [string] $Source
- # Destination directory.
- [string] $Dest
- # If true, rename the existing folder with a date suffix, then copy
- # source files to a new folder at the path.
- [boolean] $MakeBackup
- # If true, skip re-copying files if only timestamps are different.
- [boolean] $IgnoreTimestamps
- Choice($displayName, $source, $dest, $makeBackup, $ignoreTimestamps) {
- $this.Source = $source
- $this.Dest = $dest
- $this.DisplayName = $displayName
- $this.MakeBackup = $makeBackup
- $this.IgnoreTimestamps = $ignoreTimestamps
- }
- }
- $CHOICES = @(
- ############
- # Mixxx
- [Choice]::new(
- "Mixxx: Desktop --> Server",
- [SourceDirs]::MixxxConfig,
- [SourceDirs]::Music_MixxxConfig,
- $true, # Make Backup
- $false # Ignore Timestamps
- ),
- [Choice]::new(
- "Mixxx: Desktop --> Drive",
- [SourceDirs]::MixxxConfig,
- [SourceDirs]::Drive_MixxxConfig,
- $true, # Make Backup
- $false # Ignore Timestamps
- ),
- [Choice]::new(
- "Mixxx: Drive --> Laptop",
- [SourceDirs]::Music_MixxxConfig,
- [SourceDirs]::MixxxConfig,
- $true, # Make Backup
- $false # Ignore Timestamps
- ),
- [Choice]::new(
- "Mixxx: Drive --> Desktop",
- [SourceDirs]::Drive_MixxxConfig,
- [SourceDirs]::MixxxConfig,
- $true, # Make Backup
- $false # Ignore Timestamps
- ),
- [Choice]::new(
- "Mixxx: Laptop --> Drive",
- [SourceDirs]::MixxxConfig,
- [SourceDirs]::Music_MixxxConfig,
- $false, # Make Backup
- $false # Ignore Timestamps
- ),
- ##########
- # iTunes
- [Choice]::new(
- "iTunes: Desktop --> Server",
- [SourceDirs]::Desktop_ITunes,
- [SourceDirs]::Music_ITunes,
- $false, # Make Backup
- $true # Ignore Timestamps
- ),
- [Choice]::new(
- "iTunes: Drive --> Server",
- [SourceDirs]::Drive_ITunes,
- [SourceDirs]::Music_ITunes,
- $false, # Make Backup
- $true # Ignore Timestamps
- ),
- [Choice]::new(
- "iTunes: Server --> Desktop",
- [SourceDirs]::Music_ITunes,
- [SourceDirs]::Desktop_ITunes,
- $false, # Make Backup
- $true # Ignore Timestamps
- ),
- ##########
- # Music
- [Choice]::new(
- "Music: Server --> Drive",
- [SourceDirs]::Music_Music,
- [SourceDirs]::Drive_Music,
- $false, # Make Backup
- $true # Ignore Timestamps
- ),
-
- ##########
- # Zip DJ
- [Choice]::new(
- "ZipDJ: Drive --> Server",
- [SourceDirs]::Drive_ZipDJ,
- [SourceDirs]::Music_ZipDJ,
- $false, # Make Backup
- $true # Ignore Timestamps
- )
- )
- # Print the given message preceded by the name of the calling function.
- function out($message) {
- $caller = (Get-PSCallStack)[1].Command
- Write-Host "${caller}: $message"
- }
- # Print the given message, preceded by the name of the calling function,
- # prompt the user to hit a key, and exit.
- function fail($message) {
- $caller = (Get-PSCallStack)[1].Command
- Write-Host "ERROR: ${caller}: $message"
- Read-Host -Prompt "Press Enter to exit"
- exit -1
- }
- function pause($message) {
- $caller = (Get-PSCallStack)[1].Command
- Write-Host "${caller}: $message`n`n"
- Read-Host -Prompt "Press Enter to continue, or CTRL+C to exit"
- }
- function GetModifiedDate($dirPath) {
- $dir = Get-Item $dirPath
- $date = Get-Date $dir.LastWriteTime
- return $date.ToShortDateString()
- }
- # Rename the specified directory to have a suffix based on the
- # last modified time.
- function makeDatedBackup($dirPath) {
- if (-not(Test-Path $dirPath)) {
- # Not an error, but nothing we can do.
- return
- }
- $modifiedDate = GetModifiedDate($dirPath)
- $newPath = "$dirPath-$modifiedDate"
- if (Test-Path $newPath) {
- $num = 2
- $newNewPath = "$newPath-$num"
- while (Test-Path $newNewPath) {
- $num++
- $newNewPath = "$newPath-$num"
- }
- out "$newPath already exists. Using $newNewPath"
- $newPath = $newNewPath
- }
- $dirName = [io.path]::GetFileName($newPath)
- out "DEBUG: Make dated backup"
- pause "Moving $dirPath to $dirName"
- Move-Item -Path $dirPath -Destination $newPath
- }
- # Synchronize the contents of two directories.
- # -NoBackup: Skip moving the existing destination to a dated backup path.
- # -IgnoreTimestamps: Skip re-copying files if only timestamps are different.
- function syncDirs {
- param (
- [string] $Source,
- [string] $Destination,
- [boolean] $MakeBackup,
- [boolean] $IgnoreTimestamps
- )
- if (($Source.Length -eq 0) -or ($Destination.Length -eq 0)) {
- fail "Both Source and Destination need to be specified."
- }
- if (-not(Test-Path $Source)) {
- fail "Source does not exist: $Source"
- }
- if ($MakeBackup) {
- out "Backing up $Destination"
- makeDatedBackup $Destination
- }
- # Docs: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/robocopy
- $roboWhat = @("/s", "/copy:DAT", "/dcopy:DAT")
- $roboOptions = @("/v", "/j")
- $roboExclude = @("/xo", "/xx")
- $roboAdditionalExcludes = @()
- if ($IgnoreTimestamps) {
- $roboAdditionalExcludes = @("/xn")
- }
-
- if ($Source -eq [SourceDirs]::MixxxConfig) {
- $roboAdditionalExcludes = @("/xd", [string]::Format("{0}\analysis", [SourceDirs]::MixxxConfig))
- }
- pause "Copying contents of: `n`t${Source}`nTo:`n`t${Destination}"
- robocopy $Source $Destination $roboWhat $roboOptions $roboExclude $roboAdditionalExcludes
- }
- function chooseSyncOption() {
- $num = 1
- Write-Host "`nPick an option to run:"
- ForEach ($o in $CHOICES) {
- Write-Host ([string]::Format("{0}) {1}", $num, $o.DisplayName))
- $num++
- }
- Write-Host "`n`n"
- Write-Host "Before an event: 1, 2, 6, 9"
- Write-Host "During an event: 3"
- Write-Host "Laptop after event: 5"
- Write-host "After an event: 7, 8, 10, 4"
- $input = Read-Host -Prompt "Enter option number"
- $choice = [int]$input
- if (($choice -lt 1) -or ($choice -gt $CHOICES.Length + 1)) {
- fail 'Invalid choice!'
- }
- return $CHOICES[$choice-1]
- }
- function Main() {
- [Choice] $option = chooseSyncOption
- $option
- syncDirs `
- -Source $option.Source `
- -Destination $option.Dest `
- -MakeBackup $option.MakeBackup `
- -IgnoreTimestamps $option.IgnoreTimestamps
- #syncDirs -Source ([SourceDirs]::MixxxConfig) -Destination ([SourceDirs]::Test) -NoBackup -IgnoreTimestamps
- pause ([string]::Format(
- "Done running {0}!`n`t{1} --> {2}",
- $option.DisplayName,
- $option.Source,
- $option.Dest
- ))
- }
- Main
|