Comment différencier deux dossiers dans Windows Powershell?

11

J'essaie de trouver des différences dans le contenu de deux structures de dossiers à l'aide de Windows Powershell. J'ai utilisé la méthode suivante pour m'assurer que les noms de fichiers sont les mêmes, mais cette méthode ne me dit pas si le contenu des fichiers est le même:

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

La technique décrite dans cette question ServerFault fonctionne pour différencier un seul fichier, mais ces dossiers contiennent des centaines de fichiers à différentes profondeurs.

La solution n'a pas nécessairement besoin de me dire ce qui est spécifiquement différent dans les fichiers - juste qu'ils le sont. Je ne suis pas intéressé par les différences de métadonnées telles que la date, que je sais déjà être différente.

David Smith
la source

Réponses:

15

Si vous souhaitez encapsuler la comparaison dans une boucle, j'opterais pour l'approche suivante:

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

        }
    }   
}

Notez que cela ignorera les fichiers qui n'existent pas à la fois dans $folder1 et $folder2.

jscott
la source
5

J'ai pris la réponse de jscott et je l'ai développée pour sortir les fichiers qui sont présents dans l'un mais pas dans l'autre pour ceux qui sont les plus intéressés par ce type de fonctionnalité. Veuillez noter que cela montre également les progrès réalisés car il était difficile pour moi de voir cela étant donné les énormes dossiers avec peu de différences. Il semblait que le script m'était accroché. Voici le code PowerShell pour cela:

$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"
    }
}
helios456
la source
Pourquoi voudriez-vous extraire le contenu réel d'un fichier lors de l'appel de Compare-Object? C'est ce que fait Compare-Object. technet.microsoft.com/en-us/library/…
Casper Leon Nielsen
1

Il vous suffit de boucler une boucle autour de la bonne réponse de votre question liée qui a déjà répondu à cela, et de parcourir l'arborescence de répertoires en comparant chaque fichier avec le même nom.

/ Edit: Si c'est vraiment votre question, c'est plus approprié pour SO, où vous semblez être un contributeur régulier. Vous posez une question de programmation. Je comprends que vous le faites pour un objectif de type sysadmin, auquel cas, je vous dirais d'utiliser un outil spécialement conçu comme WinDiff.

mfinni
la source
2
OK, ce site ne convient pas aux questions de type "Donnez-moi le code". Si vous devez commencer à apprendre à faire des boucles dans Powershell, achetez un livre ou trouvez des tutoriels en ligne; il y a beaucoup de.
mfinni
2
Je pense que tu t'es réveillé du mauvais côté du lit. Je ne suis pas un utilisateur régulier de Powershell. J'ai démontré dans ma question à la fois une technique que j'essaie actuellement et un lien vers une question qui contient des informations utiles supplémentaires pour mon problème. Je ne sais pas comment combiner les deux techniques, ce qui est mon problème, et la raison pour laquelle j'ai posé cette question. C'est aussi une question à laquelle je n'ai pas pu répondre à l'aide des recherches Google. Si vous n'allez pas être utile, pensez à supprimer votre réponse.
David Smith
2
@BigDave Littéralement le premier résultat pour PowerShell loop through filessur Google . allez maintenant - un petit effort de votre part?
voretaq7
2
@ voretaq7 Je pense que vous vous méprenez en tant qu'utilisateur PowerShell. J'ai fait cette recherche google, essayé cette technique et n'ai pas réussi. J'ai essayé d'expliquer où j'en suis dans la question ci-dessus. La question à laquelle vous liez fonctionne sur un seul ensemble de fichiers. J'ai deux ensembles que je dois comparer, nom à nom. Je n'essaie vraiment pas d'être paresseux ici. Je sais boucler et je sais comparer. Comment boucler et comparer deux ensembles?
David Smith
1
Je pense que faire ça avec PS est un super petit projet. Cependant, WinMerge (pensait que c'était WinDiff, idiot) est vraiment un excellent outil si vous allez le faire très souvent. Il est littéralement construit pour le travail. Essayez-le, le téléchargement est gratuit. Il possède des décomposeurs pour la plupart des types de fichiers et fait un excellent travail de mise en évidence, y compris des options pour la façon dont vous souhaitez gérer les espaces.
mfinni
0

Faites ceci:

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

Et même récursivement:

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

et c'est même difficile à oublier :)

Francesco Mantovani
la source