Pregunta

Quiero decir si dos archivos tarball contienen archivos idénticos, en términos de nombre de archivo y contenido del archivo, sin incluir metadatos como fecha, usuario, grupo.

Sin embargo, hay algunas restricciones: primero, no tengo control de si los metadatos se incluyen al crear el archivo tar, en realidad, el archivo tar siempre contiene metadatos, por lo que directamente los dos archivos tar no funcionan. En segundo lugar, dado que algunos archivos tar son tan grandes que no puedo permitirme descomprimirlos en un directorio temporal y diferenciar los archivos contenidos uno por uno. (Sé que si puedo descomprimir file1.tar en file1 /, puedo compararlos invocando 'tar -dvf file2.tar' en el archivo /. Pero generalmente no puedo permitirme descomprimir ni siquiera uno de ellos)

¿Alguna idea de cómo puedo comparar los dos archivos tar? Sería mejor si se puede lograr dentro de los scripts de SHELL. Alternativamente, ¿hay alguna forma de obtener la suma de comprobación de cada subarchivo sin realmente descomprimir un tarball?

Gracias,

¿Fue útil?

Solución

tarsum es casi lo que necesitas. Tome su salida, ejecútelo para obtener el orden idéntico en cada uno, y luego compare los dos con diff. Eso debería llevarlo a una implementación básica, y sería bastante fácil llevar esos pasos al programa principal modificando el código de Python para hacer todo el trabajo.

Otros consejos

¿Estás controlando la creación de estos archivos tar?
Si es así, el mejor truco sería crear una suma de comprobación MD5 y almacenarla en un archivo dentro del propio archivo. Luego, cuando desee comparar dos archivos, simplemente extraiga estos archivos de suma de comprobación y compárelos.


Si puede permitirse extraer solo un archivo tar , puede usar la opción --diff de tar para buscar diferencias con el contenido de otro archivo tar.


Un truco más crudo si está bien con solo una comparación de los nombres de archivo y sus tamaños .
¡Recuerde, esto no garantiza que los otros archivos sean iguales!

ejecute un tar tvf para enumerar el contenido de cada archivo y almacenar las salidas en dos archivos diferentes. luego, corte todo aparte del nombre del archivo y las columnas de tamaño. Preferiblemente clasifique los dos archivos también. Luego, solo haga una diferencia de archivo entre las dos listas.

Solo recuerda que este último esquema realmente no tiene suma de verificación.

Ejemplo de tar y salida (todos los archivos son de tamaño cero en este ejemplo).

$ tar tvfj pack1.tar.bz2
drwxr-xr-x user/group 0 2009-06-23 10:29:51 dir1/
-rw-r--r-- user/group 0 2009-06-23 10:29:50 dir1/file1
-rw-r--r-- user/group 0 2009-06-23 10:29:51 dir1/file2
drwxr-xr-x user/group 0 2009-06-23 10:29:59 dir2/
-rw-r--r-- user/group 0 2009-06-23 10:29:57 dir2/file1
-rw-r--r-- user/group 0 2009-06-23 10:29:59 dir2/file3
drwxr-xr-x user/group 0 2009-06-23 10:29:45 dir3/

Comando para generar una lista de nombres / tamaños ordenados

$ tar tvfj pack1.tar.bz2 | awk '{printf "%10s %s\n",$3,$6}' | sort -k 2
0 dir1/
0 dir1/file1
0 dir1/file2
0 dir2/
0 dir2/file1
0 dir2/file3
0 dir3/

Puede tomar dos de estas listas ordenadas y diferenciarlas.
También puede usar las columnas de fecha y hora si eso funciona para usted.

Pruebe también pkgdiff para visualizar las diferencias entre paquetes (detecta archivos agregados / eliminados / renombrados y contenido modificado, existe con código cero si no se modifica):

pkgdiff PKG-0.tgz PKG-1.tgz

 ingrese la descripción de la imagen aquí

 ingrese la descripción de la imagen aquí

Aquí está mi variante, también está verificando el permiso de Unix:

Funciona solo si los nombres de archivo son más cortos que 200 caracteres.

diff <(tar -tvf 1.tar | awk '{printf "%10s %200s %10s\n",$3,$6,$1}'|sort -k2) <(tar -tvf 2.tar|awk '{printf "%10s %200s %10s\n",$3,$6,$1}'|sort -k2)

Me doy cuenta de que esta es una respuesta tardía, pero me encontré con el hilo mientras intentaba lograr lo mismo. La solución que he implementado genera el tar en stdout y lo canaliza al hash que elija:

tar -xOzf archive.tar.gz | sort | sha1sum

Tenga en cuenta que el orden de los argumentos es importante; particularmente O que señala usar stdout.

¿Es tardiff lo que está buscando? Es "un simple script en perl" que "compara el contenido de dos tarballs e informa sobre cualquier diferencia encontrada entre ellos".

Si no extrae los archivos ni necesita las diferencias, intente diff La opción -q :

diff -q 1.tar 2.tar

Este resultado silencioso será " 1.tar 2.tar diferirá " o nada, si no hay diferencias.

Hay una herramienta llamada archdiff . Básicamente es una secuencia de comandos perl que puede examinar los archivos.

Takes two archives, or an archive and a directory and shows a summary of the
differences between them.

Tengo una pregunta similar y la resuelvo por python, aquí está el código. ps: aunque este código se usa para comparar el contenido de dos zipball, pero es similar al tarball, espero poder ayudarte

import zipfile
import os,md5
import hashlib
import shutil

def decompressZip(zipName, dirName):
    try:
        zipFile = zipfile.ZipFile(zipName, "r")
        fileNames = zipFile.namelist()
        for file in fileNames:
            zipFile.extract(file, dirName)
        zipFile.close()
        return fileNames
    except Exception,e:
        raise Exception,e

def md5sum(filename):
    f = open(filename,"rb")
    md5obj = hashlib.md5()
    md5obj.update(f.read())
    hash = md5obj.hexdigest()
    f.close()
    return str(hash).upper()

if __name__ == "__main__":
    oldFileList = decompressZip("./old.zip", "./oldDir")
    newFileList = decompressZip("./new.zip", "./newDir")

    oldDict = dict()
    newDict = dict()

    for oldFile in oldFileList:
        tmpOldFile = "./oldDir/" + oldFile
        if not os.path.isdir(tmpOldFile):
            oldFileMD5 = md5sum(tmpOldFile)
            oldDict[oldFile] = oldFileMD5

    for newFile in newFileList:
        tmpNewFile = "./newDir/" + newFile
        if not os.path.isdir(tmpNewFile):
            newFileMD5 = md5sum(tmpNewFile)
            newDict[newFile] = newFileMD5

    additionList = list()
    modifyList = list()

    for key in newDict:
        if not oldDict.has_key(key):
            additionList.append(key)
        else:
            newMD5 = newDict[key]
            oldMD5 = oldDict[key]
            if not newMD5 == oldMD5:
            modifyList.append(key)

    print "new file lis:%s" % additionList
    print "modified file list:%s" % modifyList

    shutil.rmtree("./oldDir")
    shutil.rmtree("./newDir")

También hay diffoscope , que es más genérico y permite comparar cosas de forma recursiva (incluidos varios formatos).

pip install diffoscope

Se puede usar un script simple:

#!/usr/bin/env bash
set -eu

tar1=$1
tar2=$2
shift 2
tar_opts=("$@")

tmp1=`mktemp -d`
_trap="rm -r "$tmp1"; ${_trap:-}" && trap "

Se puede usar un script simple:

diff-tars.sh TAR1 TAR2 [DIFF_OPTS]

Uso:

<*>trap" EXIT tar xf "$tar1" -C "$tmp1" tmp2=`mktemp -d` _trap="rm -r "$tmp2"; ${_trap:-}" && trap "

Se puede usar un script simple:

<*>

Uso:

<*>trap" EXIT tar xf "$tar2" -C "$tmp2" diff -ur "${tar_opts[@]:+${tar_opts[@]}}" "$tmp1" "$tmp2"

Uso:

<*>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top