Obtener una lista de archivos que existen en una carpeta pero no en otra, según lo determinado por el contenido, no por el nombre del archivo, en Windows

Obtener una lista de archivos que existen en una carpeta pero no en otra, según lo determinado por el contenido, no por el nombre del archivo, en Windows

Dados 2 directorios (DirA y DirB), ¿cuál es la forma más eficiente de encontrar una lista de archivos que existen en DirA pero que no existen en DirB?

Intenté hacer esto usando la jdupes.exe --printunique --recurse -Oherramienta, sin embargo, esto tiene el efecto secundario de excluir un archivo que cumple con los criterios anteriores si existen duplicados de dicho archivo en DirA.

Los archivos pueden estar en subdirectorios completamente diferentes de DirA y DirB y pueden tener nombres diferentes. Por tanto, el contenido del archivo es la única característica duradera.

Respuesta1

Las cuerdas regresaron dePotencia Shell'sObtener-FileHashpueden usarse como las llaves de untabla de picadillopara asociar contenido con la ruta de acceso completa. Este código crea una tabla hash para cada ruta con las siguientes advertencias.

  • Los archivos vacíos se ignoran ya que el hash de contenido de todos los archivos vacíos será idéntico. (También puede crear una lista de archivos vacíos en cada directorio)
  • Si se encuentran duplicadosdentroel directorio que estamos indexando, solo se agregará a la $HashOuttabla el primer archivo encontrado. La $Dupstabla tendrá la lista de todas las rutas que comparten contenido idéntico.

Potencia Shell:

Function Get-DirHash ( [String]$PathIn , [PSObject]$HashOut )
{
    $HashOut.Clear()
    gci $PathIn *.txt -Recurse | ? Length -gt 0 | Get-FileHash | %{
        If ( $HashOut.Contains($_.Hash) )
        {
            If ( $Dups.Contains($_.Hash) )
            {
                $Dups[$_.Hash] += $_.Path
            }
            Else
            {
                $Dups.Add( $_.Hash , @( $HashOut[$_.Hash] , $_.Path ))
            }
        }
        Else
        {
            $HashOut.Add( $_.Hash , $_.Path )
        }
    }
}

$DirA     = 'c:\whatever'
$DirB     = 'c:\whenever'
$TableA   = @{}
$TableB   = @{}
$Dups     = @{}
$Unique2A = New-Object System.Collections.Generic.List[String]

Get-DirHash -PathIn $DirA -HashOut $TableA
Get-DirHash -PathIn $DirB -HashOut $TableB

$TableA.Keys | %{
    If ( ! ( $TableB.Contains($_) ))
    {
        $Unique2A.Add( $TableA[$_] )
    }
}

$Unique2A | Out-GridView



No está completamente probado, pero creo que esto funcionará para calcular solo el hash de archivos que coincidan en tamaño.

$DirA     = 'c:\whatever'
$DirB     = 'c:\whenever'

$TestA = [Regex]::Escape($DirA)

$MasterList = gci $DirA , $DirB -Filter *.txt -recurse | Group Length

$Unique2A_BySize = ( $MasterList | ? Count -eq 1 |
     ? { $_.Group[0].DirectoryName -match $TestA } ).Group.FullName

$Unique2A_ByHash = ( $MasterLIst | ? Count -gt 1 | %{
    $_.Group | Get-FileHash | Group Hash |
        ? Count -eq 1 |
           ? { $_.Group[0].Path -match $TestA }
} ).Group.Path

( $Unique2A = $Unique2A_BySize + $Unique2A_ByHash ) | Out-GridView

Lo cual puede mejorarse con los más difíciles de leer:

$DirA     = 'c:\whatever'
$DirB     = 'c:\whenever'

$TestA = [Regex]::Escape($DirA)

$Unique2A = ( ( $MasterList = gci $DirA , $DirB -Filter *.txt -recurse | Group Length ) |
    ? Count -eq 1 |
        ? { $_.Group[0].DirectoryName -match $TestA } ).Group.FullName +
( $MasterLIst | ? Count -gt 1 | %{
    $_.Group | Get-FileHash | Group Hash |
        ? Count -eq 1 |
           ? { $_.Group[0].Path -match $TestA }
} ).Group.Path

$Unique2A | Out-GridView

Respuesta2

Copiaría las listas de directorios en Excel y usaría la función ÚNICA

información relacionada