ddoollyy

Einen Hash über Powershell erstellen für mehrere Dateien

Hey an Alle,

Ich habe zurzeit die Aufgabe, aus Archivierungsgründen eine Hash über meine Powerschell zu erstellen, die alle Dateien in einem Ordner in insgesamt einer Prüfsumme sammelt. Ich habe bisschen gegoogelt, gefunden habe ich bis jetzt nur wie ich mit "Get-FileHash" eine Hash für jeweils eine Datei erzeuge. Es bringt mir leider auch nichts, nur die Prüfsumme von dem Ordner zu erstellen, es sollen am besten alle Dateien in diesem Ordner gelistet sein, da mir gesagt wurde, dass die Prüfsumme nicht mehr stimmen wird beim Vergleich. Gibt es einen Befehl, wo ich, vielleicht mit Get-FileHash, alle Dateien aufliste und die Shell mir dann eine einzige Hash erzeugt?


Liebe Grüße,
Robin face-smile
Auf Facebook teilen
Auf X (Twitter) teilen
Auf Reddit teilen
Auf Linkedin teilen

Content-ID: 7029464841

Url: https://administrator.de/forum/einen-hash-ueber-powershell-erstellen-fuer-mehrere-dateien-7029464841.html

Ausgedruckt am: 13.07.2025 um 13:07 Uhr

Kraemer
Kraemer 05.05.2023 aktualisiert um 15:42:14 Uhr
Moin,

du solltest dir unbedingt mal die Beschreibung von Get-FileHash ansehen. Ganz wichtig dabei ist die Informationen wovon eigentlich ein Hash erstellt wird.
emeriks
emeriks 05.05.2023 um 16:01:16 Uhr
Hi,
von jeder Datei eines Verzeichnis einen Hash erzeugen mit Get-Hash. Diese Hash alle in eine Datei schreiben lassen.
Von dieser einen Datei einen Hash erstellen. --> Das ist dann Dein Hash pro verzeichnis.

E.
DerWoWusste
Lösung DerWoWusste 05.05.2023 um 16:05:56 Uhr
7zip macht das ordentlich:

"c:\Program Files\7-Zip\7z.exe" h -scrcsha256 "c:\ordner"  
7010350221
Lösung 7010350221 05.05.2023 aktualisiert um 16:15:39 Uhr
$allhashes = (Get-ChildItem "E:\Ordner" -File -Recurse | Get-FileHash -Algorithm SHA256).Hash -join ''  
$folderHash = [System.BitConverter]::ToString([System.Security.Cryptography.HashAlgorithm]::Create("SHA256").ComputeHash([System.Text.Encoding]::ASCII.GetBytes($allhashes))).replace('-','')  

Gruß pille
Kraemer
Kraemer 05.05.2023 um 16:10:54 Uhr
Zitat von @DerWoWusste:

7zip macht das ordentlich:

"c:\Program Files\7-Zip\7z.exe" h -scrcsha256 "c:\ordner"  

man könnte auch die Ausgabe von

Get-FileHash c:\temp\*

ein eine Datei schreiben
3063370895
Lösung 3063370895 05.05.2023 aktualisiert um 16:19:46 Uhr
$folder = "D:\tmp\"  

$tempFile = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName())
Get-ChildItem -Recurse -File $folder | Get-FileHash | Select-Object Hash | Set-Content $tempFile
$folderHash = Get-FileHash $tempFile
Remove-Item $tempFile -Force

-Thomas
Kraemer
Lösung Kraemer 05.05.2023 aktualisiert um 16:18:50 Uhr
Zitat von @3063370895:
oder

$stringAsStream = [System.IO.MemoryStream]::new()
$writer = [System.IO.StreamWriter]::new($stringAsStream)
$writer.write((Get-FileHash c:\temp\*))
$writer.Flush()
$stringAsStream.Position = 0
Get-FileHash -InputStream $stringAsStream | Select-Object Hash

bleibt aber immer noch die Frage offen, welche Intigrität eigentlich wie geprüft werden soll...
7010350221
Lösung 7010350221 05.05.2023 aktualisiert um 16:35:00 Uhr
Schnellere Hashes würde auch ein CRC32 Hash liefern, gerade bei großen Dateien spart das einiges an Zeit, das reicht manchmal schon.
Add-Type '  
using System;
using System.IO;

public static class CRC32{
    public static string ComputeHash(Stream stream){
        uint[] ChecksumTable = new uint[0x100];
        uint poly = 0xEDB88320;
        for (uint index = 0; index < 0x100; ++index){
            uint item = index;
            for (int bit = 0; bit < 8; ++bit)
                item = ((item & 1) != 0) ? (poly ^ (item >> 1)) : (item >> 1);
            ChecksumTable[index] = item;
        }
        uint result = 0xFFFFFFFF;
        int current;
        while ((current = stream.ReadByte()) != -1)
            result = ChecksumTable[(result & 0xFF) ^ (byte)current] ^ (result >> 8);

        byte[] hash = BitConverter.GetBytes(~result);
        Array.Reverse(hash);
        return BitConverter.ToString(hash).Replace("-","");  
    }
    public static string ComputeHash(byte[] data){
        using (MemoryStream stream = new MemoryStream(data))
            return ComputeHash(stream);
    }
    public static string ComputeHash (string file){
        using (FileStream stream = new FileStream(file,FileMode.Open))
            return ComputeHash(stream);
    }
}'  
$hashes = foreach($file in Get-ChildItem "E:\Ordner" -File -Recurse){[CRC32]::ComputeHash($file.Fullname)}  
$folderHash = [System.BitConverter]::ToString([System.Security.Cryptography.SHA256]::Create().ComputeHash([System.Text.Encoding]::ASCII.GetBytes($hashes))).replace('-','')  
Kraemer
Kraemer 05.05.2023 um 16:37:03 Uhr
Ist das nicht herrlich, wieviele Wege es gibt, ein nicht genauer definiertes Problem zu lösen face-big-smile
3063370895
3063370895 05.05.2023 aktualisiert um 16:42:00 Uhr
Zitat von @pille6:

Schnellere Hashes würde auch ein CRC32 Hash liefern, gerade bei großen Dateien spart das einiges an Zeit, das reicht manchmal schon.
Ist bei mir um Faktor 5 langsamer als Get-Filehash

-Thomas
7010350221
7010350221 05.05.2023 aktualisiert um 16:49:41 Uhr
Zitat von @3063370895:
Ist bei mir um Faktor 5 langsamer als Get-Filehash
Wiederhol das mal mit größeren Dateien und SHA256 face-wink Dann wirst du den Unterschied sehen ...

Hier ein Vergleich beider Methoden eines Verzeichnisses rekursiv mit 2000 Dateien im RAM, erste Zeit CRC32, zweite Zeit Get-FileHash
CRC32  = 1,1185974s
Get-FileHash = 2,629939s
3063370895
3063370895 05.05.2023 aktualisiert um 17:04:15 Uhr
Hier über einen 1,3 GB Ordner mit Videos:
2023-05-05 16_52_09-untitled-2.ps1 - visual studio code

Hier mit PS 5.1, damit keiner sagt es liegt an PS7 face-smile
2023-05-05 16_53_52-untitled-2.ps1 - visual studio code

Nicht ganz Faktor 5, aber 3-4

Hier der ganze Code:
$folder = "D:\tmp"  
 
$sha256 = Measure-Command -Expression {
    $tempFile = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName())
    Get-ChildItem -Recurse -File $folder | Get-FileHash -Algorithm SHA256| Select-Object Hash | Set-Content $tempFile
    $folderHashsha256 = Get-FileHash -Algorithm SHA256 $tempFile 
    remove-item $tempFile -force
 
} | select -expandproperty totalseconds
 
 
$crc32 = Measure-Command -Expression {
    Add-Type '  
using System;
using System.IO;
 
public static class CRC32{
    public static string ComputeHash(Stream stream){
        uint[] ChecksumTable = new uint[0x100];
        uint poly = 0xEDB88320;
        for (uint index = 0; index < 0x100; ++index){
            uint item = index;
            for (int bit = 0; bit < 8; ++bit)
                item = ((item & 1) != 0) ? (poly ^ (item >> 1)) : (item >> 1);
            ChecksumTable[index] = item;
        }
        uint result = 0xFFFFFFFF;
        int current;
        while ((current = stream.ReadByte()) != -1)
            result = ChecksumTable[(result & 0xFF) ^ (byte)current] ^ (result >> 8);
 
        byte[] hash = BitConverter.GetBytes(~result);
        Array.Reverse(hash);
        return BitConverter.ToString(hash).Replace("-","");  
    }
    public static string ComputeHash(byte[] data){
        using (MemoryStream stream = new MemoryStream(data))
            return ComputeHash(stream);
    }
    public static string ComputeHash (string file){
        using (FileStream stream = new FileStream(file,FileMode.Open))
            return ComputeHash(stream);
    }
}'  
    $hashes = foreach ($file in Get-ChildItem $folder -File -Recurse) { [CRC32]::ComputeHash($file.Fullname) }
    $folderHashcrc32 = [System.BitConverter]::ToString([System.Security.Cryptography.SHA256]::Create().ComputeHash([System.Text.Encoding]::ASCII.GetBytes($hashes))).replace('-', '')  
} | select -expandproperty totalseconds
 
[PSCustomObject]@{
    "SHA256Time" = $sha256  
    "CRC32Time"  = $crc32  
}

Ach nochwas: Ich glaube nicht, dass OP die selbe Datei im RAM 2000 mal hashen will face-smile

-Thomas