When copying a Windows profile, I am successfully copying and excluding the voluminous "AppData" folder. But the side effect is that in the backup folder, sub-folder "Documents" duplicates are showing up.
$UserProfPath = "C:\Users\" + $UserID
$UserProfPathAllItems = $UserProfPath + "\*"
$UserBkpPath = $BackupLocation + "\" + $UserID
Copy-Item -Path (Get-Item -Path $UserProfPathAllItems -Exclude ('Appdata')).FullName -Destination $UserBkpPath -Force -Recurse
This works, but it makes redundant "My Music", "My Pictures", and "My Videos" folders in the "Documents" sub-folder (but does not copy files); and that is the only redundant 3 folders it makes! Where in this logic would this line make these 3 redundant folders?
Those are hidden, system-defined junctions (junctions are akin to symbolic links to other directories) that exist solely for backward compatibility with pre-Vista versions of Windows.
E.g., the legacy path
$HOME\Documents\My Musicsimply redirects to$HOME\MusicYour
Copy-Itemcall includes-Force, which includes hidden items, so these system junctions are included in the copy operation and become regular, non-hidden, empty directories - this behavior is problematic, for the reasons discussed in the next section.Solution options:
Either: Simply delete the unwanted directories after the fact:
Or, assuming that the directory trees that you want to copy do not contain directory junctions / directory symlinks that you DO want to copy (as such), you can use
Robocopy.exewith its/XJDoption (add/SLif you want to copy file symlinks as such):Copy-Item.Background information:
You can discover these system junctions in a given directory tree as follows:
-ErrorAction Ignoreis needed, because in Windows PowerShellGet-ChildItemtries to recurse into these junctions, which fails due to lack of permissions (even when running elevated). In PowerShell (Core) 7+,Get-ChildItemno longer does that (but you may still encounter permission-denied errors when running without elevation).Target
C:\to find them on the entire C: drive, though you'll need to run with elevation (as administrator) to also see other users' system junctions.The fact that when such system junctions are copied they turn into regular directories in principle is somewhat justifiable:
As demonstrated in GitHub issue #5240, up to at least PowerShell (Core) 7.3.x (current as of this writing),
Copy-Itemcurrently invariably copies a symlink's / NTFS reparse point's target rather than the link itself.However, there are two problematic aspects (in addition to currently not being able to request that links be copied as links):
With
-Recurse, a directory link's target is normally also copied recursively.Irrespective of whether the target is a link or not,
Copy-Itemcurrently doesn't copy file-system attributes such asHidden,ReadOnly, orSystemfor directories: