PowerShell创建一个零大小文件的重复文件夹



我想创建一组文件夹的0文件大小的镜像,但是虽然robocopy非常好,但它并没有保存我想要的所有信息:

robocopy D:documents E:backupsdocuments_$(Get-Date -format "yyyyMMdd_HHmm") /mir /create

/create开关使重复文件夹中的每个文件的大小为零,这很好,但我希望重复文件夹中的每个文件在名称末尾附加[size],大小为KB或MB或GB,并且每个文件的创建/最后修改时间与原始文件完全匹配。这样,我将有一个零大小的文件夹副本,我可以存档,但它包含该目录中文件的所有相关信息,显示每个文件的大小和确切的创建/最后修改时间。

是否有好的/简单的方法在PowerShell中迭代树,并为每个项目创建一个包含所有相关信息的零大小文件,像这样?

这将是使用我在评论中提到的方法实现复制命令的一种方法。这应该会给你一些灵感。我不打算花那么多时间在上面,但我在几个目录上运行了它,发现了一些问题,并对遇到的每个问题进行了调试。这是一个非常可靠的例子。

function Copy-FolderZeroSizeFiles {
[CmdletBinding()]
param( [Parameter(Mandatory)] [string] $FolderPath, 
[Parameter(Mandatory)] [string] $DestinationPath )
$dest = New-Item $DestinationPath -Type Directory -Force
Push-Location -LiteralPath $FolderPath
try {
foreach ($item in Get-ChildItem '.' -Recurse) {

$relPath = Resolve-Path -LiteralPath $item -Relative
$type = if ($item.Attributes -match 'Directory')
{ 'Directory' }
else { 'File'      }
$destItem = New-Item "$dest$relPath" -Type $type -Force
$destItem.Attributes    = $item.Attributes
$destItem.LastWriteTime = $item.LastWriteTime
}
} finally {
Pop-Location
}
}

注意:上面的实现是简单的,并且表示任何不是目录的东西作为文件。这意味着符号链接等将是没有信息的文件,它们将被链接到什么。

这里有一个函数可以将字节数转换为n/n B/K/M/G格式。要获得更多的小数点,只需在格式字符串的末尾添加0's。

function ConvertTo-FriendlySize($NumBytes) {
switch ($NumBytes) {
{$_ -lt 1024}       { "{0,7:0.0}B" -f ($NumBytes)             ; break }
{$_ -lt 1048576}    { "{0,7:0.0}K" -f ($NumBytes / 1024)      ; break }
{$_ -lt 1073741824} { "{0,7:0.0}M" -f ($NumBytes / 1048576)   ; break }
default             { "{0,7:0.0}G" -f ($NumBytes / 1073741824); break }
}
}

通常,人们把这些转换错了。例如,使用1024 * 1000来获得兆字节是一个常见的错误(这是将1K的base10值与1K的base2值混合),并遵循相同的逻辑来获得GB和TB。

这是我在问题中提出的附加部分,根据需要更改$src/$dst(D:VMs是我保留很多虚拟机的地方)。我已经设置了所有的creatationtime, LastWriteTime, LastAccessTime,以便零大小文件的备份位置是源的完美表示。由于我想将其用于存档目的,因此我最终将内容压缩,并在压缩文件名中包含日期时间戳。

# Copy-FolderZeroSizeFiles
$src = "D:VMs"
$dst = "D:VMs-Backup"
function ConvertTo-FriendlySize($NumBytes) {
switch ($NumBytes) {
{$_ -lt 1024}       { "{0:0.0}B" -f ($NumBytes)             ; break }   # Change {0: to {0,7: to align to 7 characters
{$_ -lt 1048576}    { "{0:0.0}K" -f ($NumBytes / 1024)      ; break }  
{$_ -lt 1073741824} { "{0:0.0}M" -f ($NumBytes / 1048576)   ; break }  
default             { "{0:0.0}G" -f ($NumBytes / 1073741824); break }  
}
}
function Copy-FolderZeroSizeFiles($FolderPath, $DestinationPath) {

Push-Location $FolderPath
if (!(Test-Path $DestinationPath)) { New-Item $DestinationPath -Type Directory }
foreach ($item in Get-ChildItem $FolderPath -Recurse -Force) {

$relPath = Resolve-Path $item.FullName -Relative
if ($item.Attributes -match 'Directory') {
$new = New-Item "$DestinationPath$relPath" -ItemType Directory -Force -EA Silent
} 
else {
$fileBaseName = [System.IO.Path]::GetFileNameWithoutExtension($item.Name)
$fileExt      = [System.IO.Path]::GetExtension($item.Name)
$fileSize     = ConvertTo-FriendlySize($item.Length)
$new = New-Item "$DestinationPath$(Split-Path $relPath)$fileBaseName ($fileSize)$fileExt" -ItemType File
}
"$($new.Name) : creation $($item.CreationTime), lastwrite $($item.CreationTime), lastaccess $($item.LastAccessTime)"
$new.CreationTime = $item.CreationTime
$new.LastWriteTime = $item.LastWriteTime
$new.LastAccessTime = $item.LastAccessTime
$new.Attributes = $item.Attributes   # Must this after setting creation/write/access times or get error on Read-Only files
}
Pop-Location
}
Copy-FolderZeroSizeFiles $src $dst
$dateTime = Get-Date -Format "yyyyMMdd_HHmm"
$zipName = "$([System.IO.Path]::GetPathRoot($dst))$([System.IO.Path]::GetFileName($dst))_$dateTime.zip"
Add-Type -AssemblyName System.IO.Compression.FileSystem
[IO.Compression.ZipFile]::CreateFromDirectory($dst, $zipName)

最新更新