将数据从一个 NTFS 驱动器移动到另一个 NTFS 驱动器时保留所有时间戳

Dev*_*ath 6 powershell file-transfer

我想将包含许多子文件夹和文件 xe2\x80\x94 的文件夹 \xe2\x80\x94 从一个 NTFS 驱动器移动到另一个 NTFS 驱动器,但我需要从新目标驱动器上的原始源保留元数据日期和时间戳属性值。

\n\n

问题:我注意到,当我完成任务的各种复制操作时,“创建日期”、“上次修改日期”等的时间戳值不会保留在至少包含一个文件夹/文件的文件夹中。我还注意到,移动的空文件夹最终会自动更改其创建日期,以与其余文件夹以及在新驱动器上的空文件夹中放置某些内容时保持一致。

\n\n

在此输入图像描述

\n\n

我的努力:我已经尝试了几乎所有可以通过 Google 找到的关于此主题的内容(Robocopy、Richcopy、Microsoft SyncToy、Total Commander、Free Commander...以及很多很多...)\xe2\x80\x94all产生相对相同的结果。没有任何东西能够对被移动的源进行全面、100% 的保存。Robocopy 和 Richcopy(以及“Commanders”)很接近,但我仍然遇到问题(在所有情况下),即创建日期被错误地“保留”,最后修改的日期根本无法保留,等等。唯一真正的承诺我还看到了除此之外的……Powershell。

\n\n
\n\n

我的 PowerShell 之旅

\n\n

我偶然发现了这个链接:

\n\n

/sf/ask/2446633801/

\n\n

...使用这个脚本:

\n\n
function Move-FileWithTimestamp {\n[cmdletbinding()]\nparam(\n[Parameter(Mandatory=$true,Position=0)][string]$Path,\n[Parameter(Mandatory=$true,Position=1)][string]$Destination\n)\n\n$origLastAccessTime = ( Get-Item $Path ).LastAccessTime\n$fileName = ( Get-Item $Path ).Name\nMove-Item -Path $Path -Destination $Destination\n$(Get-Item ($Destination+\'\\\'+$fileName)).LastAccessTime = \n$origLastAccessTime\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

上面线程中的脚本仍然没有与我列出的程序执行任何不同,但至少在这里,我有一个平台,我可以在其中更改/自定义/调整一些东西以满足我的确切需求。因此,我用我在这个领域有限的知识做了我能做的(即用“.CreationTime”更改“.LastAccessTime”,用“LastWriteTime”交换“.LastAccessTime”等),并最终相对接近保留所有时间戳(我相信在某一时刻,我已将上次修改、上次访问和上次保存保存在我的测试文件夹中)。但是,我似乎仍然无法正确保留创建日期,并且我能够用其他所有内容完成的工作显然仅适用于单独的测试文件夹(没有其他内容,例如其中的子文件夹......但这就是只是因为我不知道如何在主目录之外编写这些内容的脚本)。

\n\n

当谈到这个问题时,我感到很困惑,所以我想知道是否有人想解决这个问题。

\n\n

更新:这就是我现在所在的位置:

\n\n
function Move-FileWithTimestamp {\n[cmdletbinding()]\nparam(\n[Parameter(Mandatory=$true,Position=0)][string]$Path,\n[Parameter(Mandatory=$true,Position=1)][string]$Destination\n)\n$origCreationTime = ( Get-Item $Path ).CreationTime\n$origLastWriteTime = ( Get-Item $Path ).LastWriteTime\n$origLastAccessTime = ( Get-Item $Path ).CreationTime\n\n$fileName = ( Get-Item $Path ).Name\nMove-Item -Path $Path -Destination $Destination\n$(Get-Item ($Destination+\'\\\'+$fileName)).CreationTime = $origCreationTime\n$(Get-Item ($Destination+\'\\\'+$fileName)).LastWriteTime = \n$origLastWriteTime\n$(Get-Item ($Destination+\'\\\'+$fileName)).LastAccessTime = \n$origLastAccessTime\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这似乎保持了被移动的主文件夹的原始创建时间(以及最后修改/写入时间),但显然最后访问时间在此过程中更改为原始创建时间(似乎当文件夹被移动时)移动到新驱动器时,Windows 默认情况下会更改该过程中的上次访问时间,并且还引用此新的上次访问时间在其新位置创建文件夹的新创建时间(它不引用原始创建时间,无论如何)。IE 如果您尝试将新的创建时间设置为等于原始创建时间,则不会有任何结果,因为新的上次访问时间默认情况下会自动将新的创建时间更改为等于它。因此,如果您强制Windows使新的上次访问时间等于原始创建时间,那么您最终会得到正确的创建时间,但上次访问时间不正确。

\n\n

所以,现在我陷入了错误的上次访问时间,但其他所有内容的时间都是正确的。另外,我不知道如何将其应用到所有子文件夹,所以如果有人知道如何做到这一点,请告诉我。

\n\n

更新:

\n\n
function Move-FileWithTimestamp {\n[cmdletbinding()]\nparam(\n[Parameter(Mandatory=$true,Position=0)][string]$Path,\n[Parameter(Mandatory=$true,Position=1)][string]$Destination\n)\n$origCreationTime = ( Get-Item $Path ).CreationTime\n$origLastWriteTime = ( Get-Item $Path ).LastWriteTime\n$origLastAccessTime = ( Get-Item $Path ).CreationTime\n$origChildCreationTime = ( Get-ChildItem $Path ).CreationTime\n$origChildLastWriteTime = ( Get-ChildItem $Path ).LastWriteTime\n$origChildLastAccessTime = ( Get-ChildItem $Path ).CreationTime\n\n\n$fileName = ( Get-Item $Path ).Name\nMove-Item -Path $Path -Destination $Destination\n$(Get-Item ($Destination+\'\\\'+$fileName)).CreationTime = $origCreationTime\n$(Get-Item ($Destination+\'\\\'+$fileName)).LastWriteTime = $origLastWriteTime\n$(Get-Item ($Destination+\'\\\'+$fileName)).LastAccessTime = \n$origLastAccessTime\n$(Get-ChildItem ($Destination+\'\\\'+$fileName)) | ForEach-Object { \n$_.CreationTime = $origChildCreationTime }\n$(Get-ChildItem ($Destination+\'\\\'+$fileName)) | ForEach-Object { \n$_.LastWriteTime = $origChildLastWriteTime }\n$(Get-ChildItem ($Destination+\'\\\'+$fileName)) | ForEach-Object { \n$_.LastAccessTime = $origChildLastAccessTime }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在,我有一个主文件夹和一个子文件夹,如果它是具有正确创建和上次修改日期(但不是上次访问日期)的子文件夹。我不知道如何为主文件夹中的其余子文件夹以及这些子文件夹中的任何子文件夹完成此操作。

\n

Vom*_*yle 6

移动目录树并保留所有时间戳属性值

因此,您的目标是确保从源位置移动到目标位置的文件和文件夹的LastWriteTimeLastAccessTimeCreationTime属性值保留在其来源位置。

本质上就是这个。。。

脚本

$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
       }
    }
Run Code Online (Sandbox Code Playgroud)

更多资源