Jak różnicować dwa foldery w programie Windows Powershell?


11

Próbuję znaleźć różnice w zawartości dwóch struktur folderów za pomocą programu Windows Powershell. Użyłem następującej metody, aby upewnić się, że nazwy plików są takie same, ale ta metoda nie mówi mi, czy zawartość plików jest taka sama:

$firstFolder = Get-ChildItem -Recurse folder1
$secondFolder = Get-ChildItem -Recurse folder2
Compare-Object -ReferenceObject $firstFolder -DifferenceObject $secondFolder

Technika opisana w tym pytaniu ServerFault działa na różnicowanie pojedynczego pliku, ale te foldery zawierają setki plików na różnych głębokościach.

Rozwiązanie niekoniecznie musi mi powiedzieć, co konkretnie w plikach jest inne - po prostu, że są. Nie interesują mnie różnice w metadanych, takich jak data, które już wiem, że są różne.

Odpowiedzi:


15

Jeśli chcesz zawinąć porównanie w pętlę, wybrałbym następujące podejście:

$folder1 = "C:\Users\jscott"
$folder2 = "C:\Users\public"

# Get all files under $folder1, filter out directories
$firstFolder = Get-ChildItem -Recurse $folder1 | Where-Object { -not $_.PsIsContainer }

$firstFolder | ForEach-Object {

    # Check if the file, from $folder1, exists with the same path under $folder2
    If ( Test-Path ( $_.FullName.Replace($folder1, $folder2) ) ) {

        # Compare the contents of the two files...
        If ( Compare-Object (Get-Content $_.FullName) (Get-Content $_.FullName.Replace($folder1, $folder2) ) ) {

            # List the paths of the files containing diffs
            $_.FullName
            $_.FullName.Replace($folder1, $folder2)

        }
    }   
}

Zauważ, że to zignoruje pliki, które nie istnieją zarówno w, jak $folder1 i $folder2.


5

Wziąłem odpowiedź jscotta i rozszerzyłem ją, aby wyświetlać pliki, które są obecne w jednym, ale nie w drugim, dla tych, którzy są zainteresowani tego rodzaju funkcjonalnością. Pamiętaj, że pokazuje także postępy, ponieważ ciężko mi było to zauważyć, biorąc pod uwagę ogromne foldery z niewielkimi różnicami. Wyglądało na to, że skrypt został mi powieszony. Oto kod PowerShell do tego:

$folder1 = "C:\Folder1"
$folder2 = "C:\Folder2"

# Get all files under $folder1, filter out directories
$firstFolder = Get-ChildItem -Recurse $folder1 | Where-Object { -not $_.PsIsContainer }

$failedCount = 0
$i = 0
$totalCount = $firstFolder.Count
$firstFolder | ForEach-Object {
    $i = $i + 1
    Write-Progress -Activity "Searching Files" -status "Searching File  $i of     $totalCount" -percentComplete ($i / $firstFolder.Count * 100)
    # Check if the file, from $folder1, exists with the same path under $folder2
    If ( Test-Path ( $_.FullName.Replace($folder1, $folder2) ) ) {
        # Compare the contents of the two files...
        If ( Compare-Object (Get-Content $_.FullName) (Get-Content $_.FullName.Replace($folder1, $folder2) ) ) {
            # List the paths of the files containing diffs
            $fileSuffix = $_.FullName.TrimStart($folder1)
            $failedCount = $failedCount + 1
            Write-Host "$fileSuffix is on each server, but does not match"
        }
    }
    else
    {
        $fileSuffix = $_.FullName.TrimStart($folder1)
        $failedCount = $failedCount + 1
        Write-Host "$fileSuffix is only in folder 1"
    }
}

$secondFolder = Get-ChildItem -Recurse $folder2 | Where-Object { -not $_.PsIsContainer }

$i = 0
$totalCount = $secondFolder.Count
$secondFolder | ForEach-Object {
    $i = $i + 1
    Write-Progress -Activity "Searching for files only on second folder" -status "Searching File  $i of $totalCount" -percentComplete ($i / $secondFolder.Count * 100)
    # Check if the file, from $folder2, exists with the same path under $folder1
    If (!(Test-Path($_.FullName.Replace($folder2, $folder1))))
    {
        $fileSuffix = $_.FullName.TrimStart($folder2)
        $failedCount = $failedCount + 1
        Write-Host "$fileSuffix is only in folder 2"
    }
}

Dlaczego miałbyś wyodrębniać rzeczywistą zawartość pliku podczas wywoływania funkcji Compare-Object? To właśnie robi porównanie. technet.microsoft.com/en-us/library/…
Casper Leon Nielsen

1

Wystarczy owinąć pętlę wokół poprawnej odpowiedzi z połączonego pytania, na które już udzielono odpowiedzi, i przejść drzewo katalogów porównując każdy plik o tej samej nazwie.

/ Edycja: Jeśli to właściwie twoje pytanie, jest bardziej odpowiednie dla SO, gdzie wydajesz się być stałym współpracownikiem. Zadajesz pytanie programistyczne. Rozumiem, że robisz to dla celu typu sysadmin, w takim przypadku powiedziałbym ci, abyś użył narzędzia zbudowanego specjalnie dla celu, takiego jak WinDiff.


2
OK, ta strona nie jest odpowiednia do pytań typu „Daj mi kod”. Jeśli chcesz zacząć uczyć się wykonywania pętli w PowerShell, kup książkę lub znajdź samouczki online; jest wiele.
mfinni

2
Myślę, że obudziłeś się po niewłaściwej stronie łóżka. Nie jestem zwykłym użytkownikiem PowerShell. W swoim pytaniu zademonstrowałem zarówno technikę, którą obecnie próbuję, jak i link do pytania, które zawiera dodatkowe pomocne informacje na temat mojego problemu. Nie wiem, jak połączyć te dwie techniki, co jest moim problemem i powodem, dla którego zadałem to pytanie. To także pytanie, na które nie byłem w stanie odpowiedzieć za pomocą wyszukiwań Google. Jeśli nie będziesz pomocny, rozważ usunięcie swojej odpowiedzi.
David Smith

2
@BigDave Dosłownie pierwszy wynik dla PowerShell loop through filesGoogle . no dalej - trochę wysiłku z twojej strony?
voretaq7,

2
@ voretaq7 Myślę, że źle zrozumieliście mnie jako użytkownika PowerShell. Zrobiłem to wyszukiwanie w Google, spróbowałem tej techniki i nie udało mi się. Próbowałem wyjaśnić, gdzie jestem w powyższym pytaniu. Pytanie, do którego linkujesz, działa na jednym zestawie plików. Mam dwa zestawy, które muszę porównać, imię i nazwisko. Naprawdę nie próbuję być tutaj leniwy. Wiem, jak zapętlić i wiem, jak porównać. Jak zapętlić i porównać dwa zestawy?
David Smith

1
Myślę, że robienie tego z PS to świetny mały projekt. Jednak WinMerge (myślałem, że to WinDiff, głupie ja) jest naprawdę świetnym narzędziem, jeśli zamierzasz to robić bardzo często. Jest dosłownie zbudowany do tego zadania. Wypróbuj, pobieranie jest bezpłatne. Ma rozkładniki dla większości typów plików i świetnie się wyróżnia, w tym opcje, jak chcesz obsługiwać białe znaki.
mfinni

0

Zrób to:

compare (Get-ChildItem D:\MyFolder\NewFolder) (Get-ChildItem \\RemoteServer\MyFolder\NewFolder)

A nawet rekurencyjnie:

compare (Get-ChildItem -r D:\MyFolder\NewFolder) (Get-ChildItem -r \\RemoteServer\MyFolder\NewFolder)

i trudno nawet zapomnieć :)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.