Powershell显示重复文件

时间:2018-04-05 07:09:54

标签: powershell

我有一项任务是检查当天是否在共享位置文件夹中导入新文件,并警告是否有任何重复文件并且不需要递归检查。

下面的代码显示了大小为1天的所有文件详细信息但是我只需要与我无法使用名称进行比较的大小相同的文件。

    struct Ball
    { 
        virtual RGB color() = 0;
    }

    struct RedBall : public Ball
    {
        RGB color() { return( RED); }
    };

    struct BlueBall : public Ball
    {
        RGB color() { return( BLUE); }
    };

    void foo( RedBall&) ...
    void foo( BlueBall&) ....

4 个答案:

答案 0 :(得分:1)

此处的所有示例仅考虑时间戳,长度和名称。这肯定是不够的。

想象一下这个例子 你有两个文件: c:\test_path\test.txtc:\test_path\temp\text.txt。 第一个包含12345。第二个包含54321。在这种情况下,即使它们不相同,这些文件也会被认为是相同的。

我根据哈希计算创建了一个重复的检查器。它现在是从我的头脑中创建的,因此它相当粗糙(但我认为你得到了这个想法并且很容易优化):

编辑我已经确定源代码“太粗糙”(昵称不正确)并且我已经改进了它(删除了多余的代码):

# The current directory where the script is executed
$path = (Resolve-Path .\).Path

$hash_details = @{}
$duplicities = @{}    

# Remove unique record by size (different size = different hash)
# You can select only those you need with e.g. "*.jpg"
$file_names = Get-ChildItem -path $path -Recurse -Include "*.*" | ? {( ! $_.PSIsContainer)} | Group Length | ? {$_.Count -gt 1} | Select -Expand Group | Select FullName, Length 

# I'm using SHA256 due to SHA1 collisions found
$hash_details =  ForEach ($file in $file_names) {
                             Get-FileHash -Path $file.Fullname -Algorithm SHA256
                         }

# just counter for the Hash table key
$counter = 0
ForEach ($first_file_hash in $hash_details) {
    ForEach ($second_file_hash in $hash_details) {
        If (($first_file_hash.hash -eq $second_file_hash.hash) -and ($first_file_hash.path -ne $second_file_hash.path)) {
                $duplicities.add($counter, $second_file_hash)
                $counter += 1
        }
    }
}

##Throw output with duplicity files 
If ($duplicities.count -gt 0) { 
    #Write-Output $duplicities.values
    Write-Output "Duplicate files found:" $duplicities.values.Path
    $duplicities.values | Out-file -Encoding UTF8 duplicate_log.txt
} Else {
    Write-Output 'No duplicities found'
}

我创建了一个测试结构:

PS C:\prg\PowerShell\_Snippets\_file_operations\duplicities> Get-ChildItem -path $path -Recurse


    Directory: C:\prg\PowerShell\_Snippets\_file_operations\duplicities


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----          9.4.2018      9:58            test
-a---          9.4.2018     11:06       2067 check_for_duplicities.ps1
-a---          9.4.2018     11:06        757 duplicate_log.txt


    Directory: C:\prg\PowerShell\_Snippets\_file_operations\duplicities\test


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----          9.4.2018      9:58            identical_file
d----          9.4.2018      9:56            t
-a---          9.4.2018      9:55          5 test.txt


    Directory: C:\prg\PowerShell\_Snippets\_file_operations\duplicities\test\identical_file


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---          9.4.2018      9:55          5 test.txt


    Directory: C:\prg\PowerShell\_Snippets\_file_operations\duplicities\test\t


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---          9.4.2018      9:55          5 test.txt

(.. \ duplicities \ test \ t中的文件与其他文件不同)。

正在运行的脚本的结果。

控制台输出:

PS C:\prg\PowerShell\_Snippets\_file_operations\duplicities> .\check_for_duplicities.ps1
Duplicate files found:
C:\prg\PowerShell\_Snippets\_file_operations\duplicities\test\identical_file\test.txt
C:\prg\PowerShell\_Snippets\_file_operations\duplicities\test\test.txt

duplicate_log.txt 文件包含更详细的信息:

Algorithm       Hash                                                                   Path                                                                                              
---------       ----                                                                   ----                                                                                              
SHA256          5994471ABB01112AFCC18159F6CC74B4F511B99806DA59B3CAF5A9C173CACFC5       C:\prg\PowerShell\_Snippets\_file_operations\duplicities\test\identical_file\test.txt             
SHA256          5994471ABB01112AFCC18159F6CC74B4F511B99806DA59B3CAF5A9C173CACFC5       C:\prg\PowerShell\_Snippets\_file_operations\duplicities\test\test.txt                            

<强>结论

如您所见,结果集中正确省略了不同的文件。

答案 1 :(得分:0)

我不喜欢这里写的类似DOS的大脚本答案,但后来发现了idiomatic tutorial

从您要查找重复项的文件夹中,只需运行这组简单的管道

Get-ChildItem -Recurse -File | 
    Group-Object Length | 
    Where-Object { $_.Count -gt 1 } | 
    select -ExpandProperty group | 
    foreach {Get-FileHash -LiteralPath $_.FullName} | 
    group -Property hash | 
    where { $_.count -gt 1 } | 
    select -ExpandProperty group

将显示所有文件及其与其他文件匹配的散列。
每行执行以下操作:

  • 获取文件
    • 从当前目录(否则使用-Path $directory
    • 递归(如果不需要,请删除-Recurse
  • 基于文件大小进行分组
  • 舍弃少于2个文件的组
  • 抓取所有这些文件
  • 获取每个哈希
  • 基于哈希的分组
  • 舍弃少于2个文件的组
  • 获取所有这些文件

添加| %{ $_.path }仅显示路径而不是哈希。
添加| %{ $_.path -replace "$([regex]::escape($(pwd)))",'' }仅显示当前目录的相对路径(在递归中很有用)。

对于提出问题的人,请不要忘记在| Where-Object {$_.CreationTime -gt (Get-Date).AddDays(-1)}之后对gci进行修改,这样就不会比较不需要考虑的文件,这可能会花费很多时间-如果您在该共享文件夹中同时有很多相同长度的文件,则会很麻烦。

最后,如果您像我一样,只是想根据姓名查找假人,因为Google可能也会带您到这里:

gci -Recurse -file | Group-Object name | Where-Object { $_.Count -gt 1 } | select -ExpandProperty group | %{ $_.fullname }

答案 2 :(得分:-1)

由于您确定要复制的文件内容。仅仅散列文件并比较散列更为谨慎。

名称,大小。 timestamp不是定义的用例的谨慎属性。由于哈希会告诉您文件是否具有相同的内容。

参见这些讨论

  

需要一种方法来检查两个文件是否相同?计算哈希值   文件。这是一种方法:   https://blogs.msdn.microsoft.com/powershell/2006/04/25/duplicate-files

     

重复文件查找器和卸妆

     

现在你等待的那一刻......一个所有的PowerShell文件   重复的发现者和卸妆!现在你可以清理所有那些副本了   图片,音乐文件和视频。该脚本将打开一个文件对话框   选择目标文件夹,递归扫描每个文件以获取副本

     

https://gallery.technet.microsoft.com/scriptcenter/Duplicate-File-Finder-and-78f40ae9

答案 3 :(得分:-1)

这可能对你有所帮助。

 $files = Get-ChildItem 'E:\SC' | Where-Object {$_.CreationTime -eq (Get-Date).AddDays(-1)} | Group-Object -Property Length
foreach($filegroup in $allfiles)
{
if ($filegroup.Count -ne 1)
{
    foreach ($file in $filegroup.Group)
    {
        Invoke-Item $file.fullname
    }
}
}