Sometimes we need to move the profiles to a new folder, drive… due to space requirements for example.
The usual way is via the graphical interface:

Powershell - Script to move profile folders 1

But performing this action for a set of users can take us a lot of time and, as a sysadmin should think, the best way to complete this tasks is to work some time developing a script to make our computers and servers perform the high load tasks (they do the simple and repetitive tasks in less time and better).

This is the script you can download here:

Param(
  [string] $ACCOUNT = "ALL",
  [string] $NEWPATH = "D:\users"
)

# Obtain all user profiles (excluding system profiles)
$USER_PROFILES = dir -LiteralPath "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" | ? {$_.name -match "S-1-5-21-"} 
 
# Loop to process all profiles
foreach ($USER_PROFILE in $USER_PROFILES) {

    # Obtain registry, profile path, user and profile new path
    $REGISTRY = $($($USER_PROFILE.pspath.tostring().split("::") | Select-Object -Last 1).Replace("HKEY_LOCAL_MACHINE","HKLM:"))
    
    $OLD_PROFILEPATH = $(Get-ItemProperty -LiteralPath $REGISTRY -name ProfileImagePath).ProfileImagePath.tostring()
    
    $USER=$OLD_PROFILEPATH.Split("\")[-1]
    $NEW_PROFILEPATH = "$NEWPATH\$USER"
	
    # Process all or the user passed as parameter?
    If ($ACCOUNT -eq "ALL" -or $USER -eq $ACCOUNT)
    {
        Write-Host "User:		$USER"
        Write-Host "Registry:	$REGISTRY"
        Write-Host "Old path:	$OLD_PROFILEPATH"
        Write-Host "New path:	$NEW_PROFILEPATH"
        Write-Host

        # Change the profile path in the registry
        Set-ItemProperty -LiteralPath $REGISTRY -Name ProfileImagePath -Value $NEW_PROFILEPATH
        
        Write-Host "- Modified Windows registry (ProfileImagePath)"
        Write-Host "- Copying folders to new location ($NEW_PROFILEPATH)..."

        # Move the profile folders to the new location
        $ROBOCOPY_COMMAND = "robocopy /e /MOVE /copyall /r:0 /mt:4 /b /nfl /xj /xjd /xjf $OLD_PROFILEPATH $NEW_PROFILEPATH > robocopy_$USER.log"
        
        Invoke-Expression $ROBOCOPY_COMMAND
        
        Write-Host "- Done!"
        Write-Host "-------------------------------"		
    }
} 

This script has 2 non-mandatory parametrs:

  1. $ACCOUNT: f.e "user1" or "ALL" for all users
  2. $NEWPATH: New profiles path -> f.e "D:\USER_PROFILES" (default value is "D:\users")


Execution examples:

# PS> .\MOVE_PROFILES.ps1 (moves all user profiles to the new location D:\users\" 
# PS> .\MOVE_PROFILES.ps1 user1 (moves user1 profile to the new location D:\users\" 
# PS> .\MOVE_PROFILES.ps1 user1 G:\folder (moves user1 profile to the path G:\FOLDER\" 
# PS> .\MOVE_PROFILES.ps1 ALL G:\folder (moves all user profiles to the path G:\FOLDER\"

Output example:

PS D:\SCRIPTS\MOVE_PROFILES> .\PROFILES.ps1  user1 "D:\PROFILES"
User:           user1
Registry:       HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\S-1-5-21-3549344377-1765089156-3850068664-9587
Old path:       D:\users\user1
New path:       D:\PROFILES\user1

- Modified Windows registry (ProfileImagePath)
- Moving folders to new location (D:\PROFILES\user1)...
- Done!
-------------------------------

A robocopy log file is generated for each user:

Powershell - Script to move profile folders 2