Clear
$NewRootPath = "$env:USERPROFILE\OneDrive - MYDOMAIN\User Profile"
$regUSF = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"
$regSF = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" 
 
$Folders = "Personal,My Pictures,My Music,My Video,Favorites,Desktop"
$Folders = $Folders.Split(",")
$FolderNames = "Documents,Pictures,Music,Videos,Favorites,Desktop"
$FolderNames = $FolderNames.Split(",")
 
$AddSize = 2000000000 #free space in Bytes to add if files are on a different volume (2000000000 = about 2 GB)
 
$ArrayPosition = -1
 
Function Move-KnownFolderPath {
    Param (
            [Parameter(Mandatory = $true)]
            [ValidateSet('Desktop', 'Documents', 'Downloads', 'Favorites', 'Music', 'Pictures', 'Videos')]
            [string]$KnownFolder,
            [Parameter(Mandatory = $true)]
            [string]$Path
    )
 
    # Known Folder GUIDs
    $KnownFolders = @{
        'Desktop' = @('B4BFCC3A-DB2C-424C-B029-7FE99A87C641');
        'Documents' = @('FDD39AD0-238F-46AF-ADB4-6C85480369C7','f42ee2d3-909f-4907-8871-4c22fc0bf756');
        'Downloads' = @('374DE290-123F-4565-9164-39C4925E467B','7d83ee9b-2244-4e70-b1f5-5393042af1e4'); #not in use - just in case you want to use it..
        'Favorites' = '1777F761-68AD-4D8A-87BD-30B759FA33DD';
        'Music' = @('4BD8D571-6D19-48D3-BE97-422220080E43','a0c69a99-21c8-4671-8703-7934162fcf1d');
        'Pictures' = @('33E28130-4E1E-4676-835A-98395C3BC3BB','0ddd015d-b06c-45d5-8c4c-f59713854639');
        'Videos' = @('18989B1D-99B5-455B-841C-AB7C74E4DDFC','35286a68-3c57-41a1-bbb1-0eae73d76c95');
    }
 
    $FolderGUID = ([System.Management.Automation.PSTypeName]'KnownFolders').Type
 #create the Type entry if it does not yet exist / relates to the Registry eventually
    If (-not $FolderGUID) {
        $KnownFolderGUID = @'
[DllImport("shell32.dll")]
public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, IntPtr token, [MarshalAs(UnmanagedType.LPWStr)] string path);
'@
        $FolderGUID = Add-Type -MemberDefinition $KnownFolderGUID -Name 'KnownFolders' -Namespace 'SHSetKnownFolderPath' -PassThru
    }
 
    If(!(Test-Path $Path)){
 #in case folder does yet exist, we create it
 Try {
 New-Item -Path $Path -Type Directory -Force -ErrorAction SilentlyContinue
 } Catch {}
    }
 #set the new folder path
 ForEach ($TmpGUID in $KnownFolders[$KnownFolder]) {
 $tmp = $FolderGUID::SHSetKnownFolderPath([ref]$TmpGUID, 0, 0, $Path) 
 } 
 Attrib +r $Path #needed to retain the icon 
}
 
ForEach ($Folder In $Folders)
{ 
 $ArrayPosition += 1
    Write-Host "Working on folder"$FolderNames[$ArrayPosition] -BackgroundColor DarkGreen
    $SourcePath = (Get-ItemProperty -Path $regUSF -Name $Folder).$Folder
    If ($SourcePath.Length -gt 0)
    {
 Write-Host "..checking source path: $SourcePath"
 If ((Test-Path -Path $SourcePath)){
 Write-Host "....path is accessible"
 $CompSource = Get-Item -Path $SourcePath
 $CompareResult = $false
 If ((Test-Path -Path ($NewRootPath + "\" + $CompSource.Name))){
 $CompTarget = Get-Item -Path ($NewRootPath + "\" + $CompSource.Name)
 Write-Host "..Comparing Source Path: "$CompSource.FullName
 Write-Host "....with Target Path:    "$CompTarget.FullName
 If ($CompSource.FullName.ToLower() -eq $CompTarget.FullName.ToLower()){
 $CompareResult = $true
 } Else {
 $CompareResult = $false
 }
 } Else {
 Write-Host "..Target Path does not exist"
 }
 If ($CompareResult -eq $true){
 Write-Host "..Source and Target path are identical: $CompTarget" -ForegroundColor Yellow
 Write-Host "....Not applying any changes!" -ForegroundColor Yellow
 Pause
 } Else {
 $SourceFolder = Get-Item -Path $SourcePath
 Write-Host "..accessing source folder $SourceFolder" -ForegroundColor Green
 If (!(Test-Path -Path ($NewRootPath + '\' + $SourceFolder.Name))){
 Move-KnownFolderPath -KnownFolder ("" + $FolderNames[$ArrayPosition] + "") -Path ($NewRootPath + '\' + $FolderNames[$ArrayPosition])
 $TargetPath = Get-Item -Path ("$NewRootPath\" + $FolderNames[$ArrayPosition])
 Write-Host "..created new folder $TargetPath"
 
 #compare source size with target free space here
 Write-Host "..Comparing Source and Target drive letters"
 If ($NewRootPath.SubString(0,2).ToLower() -ne $SourcePath.SubString(0,2).ToLower())
 {
 #source drives are different.. we need to obey the SourceSize against the free space on the target
 Write-Host "....Source and Target drive letters are different"
 Write-Host "......Please wait while calculating the source size"
 $SourceSize = (Get-ChildItem -Path $SourcePath -Recurse | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum
 $TargetFree = Get-PSDrive $NewRootPath.SubString(0,1) | Select-Object Free
 If ($SourceSize -gt $TargetFree.Free) {
 Write-Host "......The Source size of $SourceSize Bytes is bigger then the free space on the Target of $TargetFree.Free Bytes" -ForegroundColor Red
 } ElseIf (($SourceSize + $AddSize) -gt $TargetFree.Free) {
 Write-Host "......The Source size of $SourceSize Bytes is close to the free space on the Target of $TargetFree.Free Bytes" -ForegroundColor Yellow
 } Else {
 Write-Host "......The Source size of $TargetFree.Free Bytes is sufficient to hold the data from the Source of $SourceSize Bytes" -ForegroundColor Green
 }
 Pause
 } Else {
 Write-Host "....Source and Targets are on the same drive, all good"
 }
 
 Write-Host "..Moving data from: $SourcePath"
 Write-Host "....to folder:      $TargetPath"
 Write-Host "....This can take several minutes..."
 Move-Item -Path ("" + $SourcePath + "\*") -Destination $TargetPath -Force -ErrorAction SilentlyContinue
 Write-Host "....Done moving data"
 } Else {
 Write-Host "..Warning - Target Path exists already: $CompTarget" -ForegroundColor Yellow
 Write-Host "....Files will not be moved, registry still will be adjusted to the target path!" -ForegroundColor Yellow
 Pause
 Move-KnownFolderPath -KnownFolder ("" + $FolderNames[$ArrayPosition] + "") -Path ($NewRootPath + '\' + $FolderNames[$ArrayPosition])
 Write-Host "....Finished adjusting registry"
 }
 Write-Host "..Trying to remove $SourcePath"
 Pause
 Try {
 Attrib -r -s $SourceFolder.FullName 
 Remove-Item -Path $SourceFolder.FullName -Force -Confirm:$false -Recurse -ErrorAction SilentlyContinue
 } Catch {} 
 Try {
 Attrib -r -s ($SourceFolder + "\desktop.ini") 
 Remove-Item -Path ($SourceFolder + "\desktop.ini") -Force -Confirm:$false -ErrorAction SilentlyContinue
 } Catch {} 
 Try {
 Rename-Item -Path $SourceFolder -NewName ($SourceFolder.Name + ".old") -Force -ErrorAction SilentlyContinue
 } Catch {} 
 }
 } Else {
 Write-Host "....SourceFolder Path invalid: $SourcePath" -ForegroundColor Red
 }
    } 
 Write-Host "..Done processing"$FolderNames[$ArrayPosition] -BackgroundColor Blue
 Pause
}
Write-Host "Script finished processing" -ForegroundColor Green
Pause