Move-Item -Exclude -Recursive Is Not leaving excluded items in place within sub directories

StackOverflow https://stackoverflow.com/questions/23637762

  •  21-07-2023
  •  | 
  •  

Question

I'm trying to move all items except a certain type of file. In this case *.msg. It does fine if the excluded file resides within the parent folder. However, the moment that same type of file is located within a subdirectory, it fails to leave the file in place and instead moves it to the new location.

username = Get-Content '.\users.txt'
foreach ($un in $username)
{
  $destA = "c:\users\$un\redirectedfolders\mydocuments"
  $destB = "c:\users\$un\redirectedfolders\desktop"
  $sourceA = "C:\users\$un\mydocuments"
  $sourceB = "C:\users\$un\desktop"

  New-Item -ItemType Directory -Path $destA, $destB

  Get-ChildItem $sourceA -Exclude '*.msg' -Recurse | Move-Item -Destination {Join-Path $destA $_.FullName.Substring($sourceA.length)}
  Get-ChildItem $sourceB -Exclude '*.msg' -Recurse | Move-Item -Destination {Join-Path $destB $_.FullName.Substring($sourceB.length)}
}
Was it helpful?

Solution

This is due to the filtering done by the Get-ChildItem exclude filter. It's kind of a known issue, and if you really want I could probably dig up some reference documentation, but it may take some time. Regardless, GCI doesn't handle wildcards very well when it comes to filtering things. What you are probably better off doing is piping it to a Where command like this:

$username = Get-Content '.\users.txt'
foreach ($un in $username)
{
  $destA = "c:\users\$un\redirectedfolders\documents"
  $destB = "c:\users\$un\redirectedfolders\desktop"
  $sourceA = "C:\users\$un\documents"
  $sourceB = "C:\users\$un\desktop"

  New-Item -ItemType Directory -Path $destA, $destB
  GCI $sourceA -recurse | ?{$_.Extension -ne ".msg" -and !$_.PSIsContainer} | %{
    $CurDest = Join-Path $destA $_.FullName.Substring($sourceA.length)
    If(!(Test-Path $CurDest.SubString(0,$CurDest.LastIndexOf("\")))){New-Item -Path $CurDest -ItemType Directory|Out-Null}
    $_ | Move-Item -Destination $CurDest
  }
  GCI $sourceB -recurse | ?{$_.Extension -ne ".msg" -and !$_.PSIsContainer} | %{
    $CurDest = Join-Path $destB $_.FullName.Substring($sourceB.length)
    If(!(Test-Path $CurDest.SubString(0,$CurDest.LastIndexOf("\")))){New-Item -Path $CurDest -ItemType Directory|Out-Null}
    $_ | Move-Item -Destination $CurDest
  }
}

Edit: Ok, now excludes folders, and also keeps folder structure.
Edit2: Re-designed to do a ForEach loop on the files, build the destination path as $CurDest, test to make sure it exists and make it if it doesn't, then move the files. Also changed mydocuments to documents which is the path to a user's My Documents folder.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top