0

感谢您阅读我的帖子和您的建议 :) 场景是,我的桌面内置了一个 HD,我收集了很多年的文件。所以有一天我做了一个外部硬盘的备份,然后我去旅行并继续从我的手机等收集照片。

从那以后,我在桌面上更改了很多文件夹结构,所以我无法比较文件夹/文件 1on1。

目标显然是,将我的外部 HD 上的所有文件复制到我的内部 HD,都放在一个名为“2SORT”的文件夹中。

我找到了一个更快的 compare-object 版本(见评论),但结果不正确,它会复制很多已经存在的文件。

这是我在 Powershell 中得到的:

cls

$path_desktop = 'C:\Files\Media\Bilder'
$path_external = 'E:\Bilder'
$path_destination = 'C:\Files\Media\Bilder\2SORT'

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

4

2 回答 2

1

如果这是您经常做的事情,我建议重构使用robocopy. 在第一次运行之后,任何后续运行都会快得多,因为robocopy旨在执行这些任务。无论您使用什么工具,第一次运行都会很慢。

Compare-Object将比较属性值。通过在其中传递一堆值将有更多工作要做。此外,在此函数运行时,您实际上并没有移动任何文件,因此如果取消此操作,则您的脚本没有移动任何内容。如果您只想比较每个文件名的列表并复制它们是否存在$ref但不存在$com,您可以限制您获得的属性,并像下面那样手动迭代/移动 $ref 中的每个。

如果您想继续使用,Compare-Object请查看它的-Property参数以限制它比较的属性数量。

$path_desktop = 'C:\Files\Media\Bilder'
$path_external = 'E:\Bilder'
$path_destination = 'C:\Files\Media\Bilder\2SORT'

$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-Member -Type Properties

Get-ChildItem -path $path_desktop -Recurse -File | Get-Member -Type Properties
于 2020-01-21T22:20:33.767 回答
0

最后我不得不通过他们的 MD5-Hash 比较文件,因为我得到了很多重复的文件,只是不同的“lastwritetime”:

cls

    $path_desktop = 'C:\Files\Media\Bilder\'
    $path_external = 'C:\Files\Media\ext'
    $path_destination = 'C:\Files\Media\Bilder\2SORT'
    $path_intcsv = 'C:\Files\Media\Bilder\inthash2.csv'
    $path_extcsv = 'C:\Files\Media\Bilder\exthash2.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
    }

于 2020-01-22T19:01:23.543 回答