首页 > 解决方案 > 大型目录树上的 Powershell 比较对象

问题描述

我正在尝试这样做:

$snap1 = Get-ChildItem -Recurse -path \\file_path1\blah | select -ExpandProperty Fullname

$snap2 = Get-ChildItem -Recurse -path \\file_path2\blah2 | select -ExpandProperty Fullname

Compare-Object -ReferenceObject $snap1 -DifferenceObject $snap2 -IncludeEqual | Out-File -FilePath C:\Users\my_username\desktop\output.txt

两个 Get-ChildItem 命令从目录树顶部的文件夹开始并向下递归,它们大部分相同,但我们需要确定两者的不同之处并让它输出完整的文件路径。一个障碍是它们每个代表大约 500 万个文件,这是一吨,一旦加载它们似乎占用了大约 20 GB 的 RAM,但是这台机器有 128 GB,所以它不是世界末日(空间效率不应该成为一个大问题)。

这个命令应该可以工作,它不会出错,它会创建“Output.txt”文件,但是没有任何东西被写入其中,它似乎只是停滞不前(我看不出它是如何运行的我知道)。

我的问题是对于更有经验的 powershell,这是命令的好语法吗?有没有更好的方法,特别是考虑到要比较的每个文件系统的大小?

编辑:

我也试过这个:

$snap1 = Get-ChildItem -Recurse -path \\server\blah$

$snap2 = Get-ChildItem -Recurse -path \\server\blah2$

Compare-Object -ReferenceObject $snap1 -DifferenceObject $snap2 | Out-File -FilePath C:\Users\user_name\Desktop\comparison.txt

哪个有相同的问题,它到达比较对象并实际上写了一些文件但似乎停止了(但是我没有提到它,因为我没有包含“equals”参数所以认为它只是没有发现很多差异.

标签: powershell

解决方案


作为起点,使用原始 .net 方法EnumerateFiles

$snap1 = [System.IO.Directory]::EnumerateFiles('S:\SCRIPTS', '*', [System.IO.SearchOption]::AllDirectories) 

如果这是一次性过程并且您需要比较相对路径,请从文件名中执行子字符串(例如删除服务器名称的前 10 个符号)

$snap1 = [System.IO.Directory]::EnumerateFiles('S:\SCRIPTS', '*', [System.IO.SearchOption]::AllDirectories) | 
    ForEach-Object { return $_.SubString(10) }

如果您需要文件名,根本没有目录名,请执行以下操作:

$snap1 = [System.IO.Directory]::EnumerateFiles('S:\SCRIPTS', '*', [System.IO.SearchOption]::AllDirectories) | 
    ForEach-Object { return [System.IO.Path]::GetFileName($_) }

...$snap2同样的方式

EnumerateFiles 工作得更快,因为Get-ChildItem它还读取FileInfo(如大小、长度、创建时间、属性等)每个文件,并且EnumerateFiles只返回全名。


推荐阅读