Special folders script

Hi all,

Me again, with another question here.

I’ve created a Windows config script, which mostly works fine, but I’ve been struggling a bit with the following.
With this script I also want to automate changing the “Special Folders” for the user.
For example, I want “C:\Users\X\Documents” to be moved to “D:\Users\X\Documents”.
Basicially I got it working, but I’m relying on some hardcoded variables, which in my eyes are a bit cumbersome at the moment.

Below are the specific lines of scripting, which I think can be tweaked a bit:

$MyDirs = "Contacts","Desktop","Documents","Downloads","Favorites","Music","Pictures","Saved Games","Videos"
$folders = [System.Enum]::GetValues[[System.Environment+SpecialFolder]]
$paden = foreach [$folder in $folders] {[System.Environment]::GetFolderPath[$folder]}
$paden2 = foreach [$MyDir in $MyDirs] {$paden |Select-Object -Unique |Where-Object {$_ -like "*$MyDir"}}

# example:
foreach [$pad in $paden2] {New-Item -Type File "$pad\textx.txt"} or copy to the new location, or something else.

The first line I use is to hardcode the folder-keywords I’m looking for to move.
The $Folders gets me a list of ALL the special folders names. Now I need to get only the ones I want (with the hardcoded MyDirs) and I also need their paths.
So the $paden shows me all of the paths and with the use of the final variable, I can filter them against my hardcoded MyDirs and continue to do whatever I want with them.
The reason I use this method, is because different versions and languages of Windows tend to have different Special Folder Paths. This way, no matter what installion I run, the folders will always be checked with the System.Environment coding.

But again, as you can see, it’s a bit overly complicated and I was wondering if there’s an easier way of doing what I’m trying to achieve here.
Comments are welcome!

Thanks in advance,


Folder Redirection is typically implemented with Group Policy. I’m not sure if there’s an easy way to do this with a script for just one user account; it’s not something I’ve tried before. Web searches are turning up some information that might be useful, but would need some testing to find out for sure.

Here’s the official documentation: http://technet.microsoft.com/en-us/library/hh848267.aspx

Thanks for your reply Dave.

I can assure it will work just fine. Especially for a home environment, you don’t want to hassle around with local policies.
My “older version” of the script used the following lines:

set MyDirs "Contacts","Desktop","Documents","Downloads","Favorites","Music","Pictures","Saved Games","Videos"
New-Item -Path $MyShell -type directory -Force
Set-Location -LiteralPath $MyShell
foreach ($MyDir in $MyDirs) {Copy-Item $HOME\$MyDir -recurse -Force}

After that part, the script makes the appropriate registry changes, to make sure the folders points to the new location.

As you can see, it relies too much on the hardcoded MyDirs variable, which would be used without checking it against the “real-world” paths.
The part I posted first, will work fine, but the use of so many variables seems unlogic to me and I’m pretty sure there must be an easier way for achieving my intended goals.

edit: apparently while copy/pasting my lines in the first post, some of the characters have been changed (parentheses became squares). Please ignore this…

If you only want to copy those directories out of all of the special folders you really have no choice to specify them in an array like that. Your code looks pretty good already. You could trim it down a little bit but it wouldn’t change the performance all that much.

Hey y’all,

A little update here. I’ve managed to create something that works better in my opinion. The following code no longer relies on hardcoded paths, instead it checks the userhome directory of the current folders which can be redirected.
The code relies on two functions though,
Show-MsgBox: for a fancy way of making the choices throughout the script
Get-RegistryKeyPropertiesAndValues: to read out the correct properties and values to adjust later on

For those who are interested, here it is:

$answer = Show-MsgBox -title "Changing the User Library Paths" -prompt "Do you want to change the user documents folder?" -BoxType YesNo -Icon Question
if [$answer -eq "Yes"]
    $MyDirs = Get-ChildItem "$HOME" -Name -Exclude "Links", "Searches"
    if [$MyDirs]
        $ShellFolder = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
        $UserShellFolder = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"
        foreach [$MyDir in $MyDirs]
            $RegName = Get-RegistryKeyPropertiesAndValues $ShellFolder |Where-Object {$_.Value -match "$MyDir"} |foreach {$_.property}
            $answer = Show-MsgBox -title "Change $MyDir Folder" -prompt "Do you want to change the $Mydir folder?" -BoxType YesNo -Icon Question
            if [$answer -eq "Yes"] 
                $inputbox = $null
                $inputbox = Show-Inputbox -message "Enter the path of the $MyDir folder" -title "Entering path..." -default "D:\Users\$env:username\$MyDir"
                if [$inputbox] 
                    if [![Test-Path "D:\Users\$env:username\$MyDir"]] {New-Item "D:\Users\$env:username\$MyDir" -ItemType Directory -Force}
                    Set-ItemProperty -Path $ShellFolder -Name $RegName -Value $inputbox
                    Set-ItemProperty -Path $UserShellFolder -Name $RegName -Value $inputbox
                    Move-Item "$HOME\$MyDir\*" "D:\Users\$env:username\$MyDir" -Force
                    attrib +r "D:\Users\$env:username\$MyDir"
                    rd $HOME\$MyDir -recurse -Force
        Show-MsgBox -title "Press OK to continue" -prompt "Folder redirection done!" -BoxType OkOnly -Icon Exclamation