Preserve all timestamps when moving data from one NTFS drive to another

Move directory tree and retain all timestamp attribute values

So your goal is to ensure that files and folders that are moved from a source location over to a destination location have their LastWriteTime, LastAccessTime, and CreationTime attribute values retained from the source location where those originated.

Essentially this. . .

  • Uses Copy-Item rather than Move-Item
  • Loops through source and sets timestamp attribute variables values to then use Set-ItemProperty to set those same values to those properties in the destination for all folders and files recursively
  • Explicitly does the same Set-ItemProperty timestamp attribute value set loop for folder objects only
  • Uses Remove-Item to then delete the original source file objects only cleaning those up
  • Uses Remove-Item to then delete the original source folder object only cleaning those up

Script

$src = "C:\Src\Folder\123\"
$dest = "X:\Dest\Folder\321\"
$src = $src.Replace("\","\\")

$i = Get-ChildItem -Path $src -Recurse
$i | % {     ## -- All files and folders

    $apath = $_.FullName -Replace $src,""
    $cpath = $dest + $apath

    Copy-Item -Path $_.FullName -Destination $cpath -Force

    If (Test-Path $cpath)
       {
           Set-ItemProperty -Path $cpath -Name CreationTime -Value $_.CreationTime
           Set-ItemProperty -Path $cpath -Name LastWriteTime -Value $_.LastWriteTime
           Set-ItemProperty -Path $cpath -Name LastAccessTime -Value $_.LastAccessTime
       }
    }

$d = Get-ChildItem -Path $src -Recurse -Directory
$d | % {     ## -- Folders only

    $apath = $_.FullName -Replace $src,""
    $cpath = $dest + $apath

    If (Test-Path $cpath)
       {
           Set-ItemProperty -Path $cpath -Name CreationTime -Value $_.CreationTime
           Set-ItemProperty -Path $cpath -Name LastWriteTime -Value $_.LastWriteTime
           Set-ItemProperty -Path $cpath -Name LastAccessTime -Value $_.LastAccessTime
       }
    }


$f = Get-ChildItem -Path $src -Recurse -File
$f | % {     ## -- Delete files only

    $apath = $_.FullName -Replace $src,"" 
    $cpath = $dest + $apath

    If (Test-Path $cpath)
       {
            Remove-Item $_.FullName -Force -ErrorAction SilentlyContinue
       }
    }


$d | % {     ## -- Delete directories only

    $apath = $_ -Replace $src,"" 
    $cpath = $dest + $apath

    If (Test-Path $cpath)
       {
            Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
       }
    }

Further Resources

  • Replace
  • Get-ChildItem
  • ForEach-Object

    Standard Aliases for Foreach-Object: the '%' symbol, ForEach

  • Copy-Item
  • If
  • Test-Path
  • Set-ItemProperty
  • Remove-Item