感谢您阅读我的帖子和您的建议:) 场景是,我的桌面上内置了一个高清,我在那里收集了多年的文件。所以有一天我备份了外部高清,然后我旅行并继续从手机等收集照片。
从那以后,我在桌面上更改了很多文件夹结构,因此我无法一对一比较文件夹/文件。
目标显然是,将我的外部HD上的所有新文件复制到我的内部HD中,全部放在名为" 2SORT"的文件夹中。
我发现了一个更快的比较对象版本(见评论(,但结果不正确,它会复制很多已经存在的文件。
这是我在Powershell中得到的:
cls
$path_desktop = 'C:FilesMediaBilder'
$path_external = 'E:Bilder'
$path_destination = 'C:FilesMediaBilder2SORT'
$ref = Get-ChildItem -path $path_desktop -Recurse -File
$com = Get-ChildItem -path $path_external -Recurse -File
$file_Diffs = Compare-Object -ReferenceObject $ref -DifferenceObject $com | Where { $_.SideIndicator -eq '=>' }
$file_Diffs |
foreach {
$copyParams = @{}
$copyParams.Path = $_.InputObject.FullName
$copyParams.Destination = "$path_destination" + $_.InputObject.Name
copy-Item @copyParams -force -PassThru | Write-Host
}
如果这是您经常做的事情,我建议重构以使用robocopy
。第一次运行后,任何后续运行都会快得多,因为robocopy
旨在执行这些任务。无论您使用什么工具,第一次运行都会很慢。
Compare-Object
将比较属性值。通过传递一堆值,它将有更多的工作要做。此外,在运行此函数时,您实际上并没有移动任何文件,因此如果取消此操作,则脚本不会移动任何内容。如果您只想比较每个文件名的列表并复制它们是否存在于$ref
但不是$com
,您可以限制您获得的属性,并像下面一样手动迭代/移动每个属性$ref。
如果您想继续使用Compare-Object
请查看它的-Property
参数来限制它正在比较的属性数量。
$path_desktop = 'C:FilesMediaBilder'
$path_external = 'E:Bilder'
$path_destination = 'C:FilesMediaBilder2SORT'
$ref = Get-ChildItem -path $path_desktop -Recurse -File | select name, fullname
$com = Get-ChildItem -path $path_external -Recurse -File | select name, fullname
$ref |
foreach {
if ($_.name -in $com | select -ExpandProperty name)
continue;
--Copy file
}
您还可以根据需要获取其他文件属性,然后您可以在进行比较时使用这些属性("手动"或使用compare-object
并迭代差异(
Get-ChildItem -path $path_desktop -Recurse -File | select Name,fullname, LastWriteTime
若要查看 Get-ChildItem 返回哪些属性,请将其传递到"获取成员类型属性"中
Get-ChildItem -path $path_desktop -Recurse -File | Get-Member -Type Properties
最后,我不得不通过MD5-Hash比较文件,因为我得到了许多重复项,只是不同的"最后写入时间":
cls
$path_desktop = 'C:FilesMediaBilder'
$path_external = 'C:FilesMediaext'
$path_destination = 'C:FilesMediaBilder2SORT'
$path_intcsv = 'C:FilesMediaBilderinthash2.csv'
$path_extcsv = 'C:FilesMediaBilderexthash2.csv'
$count=0
$res = @()
Get-ChildItem -path $path_desktop -Recurse -File | % {
Write-Host ($count++)
$hash = Get-FileHash $_.FullName -Algorithm MD5
$res += New-Object PSObject -Property @{Hash=$hash.Hash; FullName=$_.FullName}
}
$res | epcsv -path $path_intcsv -NoTypeInformation
$count=0
$res = @()
Get-ChildItem -path $path_external -Recurse -File | % {
Write-Host ($count++)
$hash = Get-FileHash $_.FullName -Algorithm MD5
$res += New-Object PSObject -Property @{Hash=$hash.Hash; FullName=$_.FullName}
}
$res | epcsv -path $path_extcsv -NoTypeInformation
$int = Import-Csv $path_intcsv
$ext = Import-Csv $path_extcsv
$IntHash = @{}
$ExtHash = @{}
$DifHash = @{}
$int | ForEach-Object {
$newKey=$_.Hash
if (!$IntHash.ContainsKey($newKey)) {
$IntHash.Add($newKey, $null)
}
}
$ext | ForEach-Object {
$newKey=$_.Hash
if (!$ExtHash.ContainsKey($newKey)) {
$ExtHash.Add($newKey, $_.FullName)
}
}
ForEach ($key in $ExtHash.Keys) {
If (!$IntHash.ContainsKey($key)) {
$DifHash.Add($key, $ExtHash[$key])
}
}
#check folder exists
if (-not (test-path $path_destination)) {
$make = new-item -ItemType directory -Path $path_destination
}
#copy files
ForEach ($key in $DifHash.Keys) {
$fullname = $DifHash[$key]
Copy-Item $fullname -Destination $path_destination -Force
}