PowerShell创建一个带有零尺寸文件的重复文件夹

发布于 2025-01-23 17:47:23 字数 448 浏览 0 评论 0原文

但它并不能保存所有我想要的信息:

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

我想创建一组文件夹的0 filesize镜像映像,但是虽然Robocopy确实很好, 重复文件夹中的文件的大小为零,这很好,但是我希望重复文件夹中的每个文件都具有[size]附加到名称末尾的,size in kb in MB或GB,以及每个文件上的创建 /最后修改时间,以与原始文件完全匹配。这样,我将拥有可以存档的文件夹的零尺寸重复,但是其中包含该目录中文件的所有相关信息,显示每个文件的大小以及确切的创建 /最后修改时间。

是否有良好 /简单的方法可以通过PowerShell中的树迭代,并且对于每个项目,都可以创建一个带有所有相关信息的零尺寸文件?

I want to create a 0-filesize mirror image of a set of folder, but while robocopy is really good, it doesn't save all of the information that I would like:

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

The /create switch makes each file in the duplicate folder have zero-size, and that is good, but I would like each file in the duplicate folder to have [size] appended to the end of the name with the size in KB or MB or GB, and the create / last modified time on every file to exactly match the original file. This way, I will have a zero-size duplicate of the folder that I can archive, but which contains all of the relevant information for the files in that directory, showing the size of each and the exact create / last modified times.

Are there good / simple ways to iterate through a tree in PowerShell, and for each item create a zero size file with all relevant information like this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小鸟爱天空丶 2025-01-30 17:47:23

这是使用我在评论中提到的方法实现复制命令的一种方法。这应该给您一些一些想法。我不打算在它上花费那么多时间,但是我在几个目录上运行了它,发现一些问题并调试了我遇到的每个问题。在这一点上,这是一个相当可靠的例子。

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
    }
}

注意:上面的实现很简单,代表任何不是文件目录的内容。这意味着符号联系等。将是文件,没有信息,他们将链接到什么。

这是一个函数,可以将转换从字节数到NN B/K/M/G格式。要获取更多小数位置,只需在格式字符串的末端添加0

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获取Megabytes(将1K的基本10值与1K的base2值混合)并遵循相同的逻辑以获取GB和TB是一个常见的错误。

This would be one way to implement the copy command using the approach I mentioned in the comments. This should give you something to pull ideas from. I didn't intend to spend as much time on it as I did, but I ran it on several directories and found some problems and debugged each problem I encountered. This is a pretty solid example at this point.

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
    }
}

Note: the above implementation is simplistic and represents anything that isn't a directory as a file. That means symbolic links, et al. will be files with no information what they would be linked to.

Here's a function to get the conversion from number of bytes to N.N B/K/M/G format. To get more decimal places, just add 0's to the end of the format strings.

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 }
    }
}

Often, people get these conversions wrong. For instance, it's a common error to use 1024 * 1000 to get Megabytes (which is mixing the base10 value for 1K with the base2 value for 1K) and follow that same logic to get GB and TB.

゛清羽墨安 2025-01-30 17:47:23

这是我提出的问题中提出的其他部分,请根据需要更改$ src/$ dst我保留大量虚拟机)。我包括设置所有创建时间,持久时间,最后一个访问时间,以便具有零尺寸文件的备份位置是源的完美表示。由于我想将其用于档案目的,因此我终于将其拉开了,并在Zipfile名称中包含了日期时间邮票。

# 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)

Here is what I came up with with the additional parts in the question, change $src / $dst as required (D:\VMs is where I keep a lot of Virtual Machines). I have included setting all of CreationTime, LastWriteTime, LastAccessTime so that the backup location with zero-size files is a perfect representation of the source. As I want to use this for archival purposes, I have finally zipped things up and included a date-time stamp in the zipfile name.

# 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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文