Linux: вычислить один хеш для данной папки и содержимого? - PullRequest
69 голосов
/ 13 февраля 2009

Наверняка должен быть способ сделать это легко!

Я пробовал приложения командной строки Linux, такие как sha1sum и md5sum, но они, похоже, способны вычислять хэши отдельных файлов и выводить список значений хэша, по одному для каждого файла.

Мне нужно сгенерировать один хеш для всего содержимого папки (не только для имен файлов).

Я бы хотел сделать что-то вроде

sha1sum /folder/of/stuff > singlehashvalue

Редактировать: чтобы уточнить, мои файлы находятся на нескольких уровнях в дереве каталогов, они не все находятся в одной корневой папке.

Ответы [ 14 ]

87 голосов
/ 13 февраля 2009

Один из возможных способов будет:

sha1sum path/to/folder/* | sha1sum

Если существует целое дерево каталогов, вам, вероятно, лучше использовать find и xargs. Одна из возможных команд будет

find path/to/folder -type f -print0 | sort -z | xargs -0 sha1sum | sha1sum

И, наконец, если вам также необходимо учитывать разрешения и пустые каталоги:

(find path/to/folder -type f -print0  | sort -z | xargs -0 sha1sum;
 find path/to/folder \( -type f -o -type d \) -print0 | sort -z | \
   xargs -0 stat -c '%n %a') \
| sha1sum

Аргументы stat заставят его напечатать имя файла с последующими восьмеричными разрешениями. Два поиска будут выполняться один за другим, вызывая удвоение количества операций ввода-вывода на диске: первый найдет все имена файлов и проверит контрольную сумму, второй найдет все имена файлов и каталогов, имя и режим печати. Список «имен файлов и контрольных сумм», за которым следуют «имена и каталоги с разрешениями», будет затем контрольной суммой для меньшей контрольной суммы.

18 голосов
/ 13 февраля 2009
  • Используйте инструмент обнаружения вторжения в файловую систему, например aide .

  • хэш тарболла из каталога:

    tar cvf - /path/to/folder | sha1sum

  • Кодируйте что-нибудь самостоятельно, например oneliner ватина :

    find /path/to/folder -type f -print0 | sort -z | xargs -0 sha1sum | sha1sum

10 голосов
/ 13 февраля 2009

Вы можете сделать tar -c /path/to/folder | sha1sum

5 голосов
/ 08 декабря 2016

Если вы просто хотите проверить, изменилось ли что-то в папке, я бы порекомендовал это:

ls -alR --full-time /folder/of/stuff | sha1sum

Он просто даст вам хэш вывода ls, который содержит папки, подпапки, их файлы, их временную метку, размер и разрешения. Почти все, что вам нужно, чтобы определить, изменилось ли что-то.

Обратите внимание, что эта команда не будет генерировать хеш для каждого файла, но поэтому она должна быть быстрее, чем использование find.

3 голосов
/ 13 февраля 2009

Если вы просто хотите хэшировать содержимое файлов, игнорируя имена файлов, тогда вы можете использовать

cat $FILES | md5sum

Убедитесь, что у вас есть файлы в том же порядке при вычислении хеша:

cat $(echo $FILES | sort) | md5sum

Но в вашем списке файлов нет каталогов.

2 голосов
/ 25 января 2011

Для этого есть скрипт на python:

http://code.activestate.com/recipes/576973-getting-the-sha-1-or-md5-hash-of-a-directory/

Если вы измените имена файлов без изменения их алфавитного порядка, хеш-скрипт не обнаружит их. Но если вы измените порядок файлов или содержимое любого файла, запуск скрипта даст вам другой хеш, чем раньше.

1 голос
/ 07 января 2018

Надежный и чистый подход

  • Перво-наперво, не забивайте доступную память ! Хеш-файл в кусках, а не кормить весь файл.
  • Различные подходы для разных нужд / целей (все нижеприведенное или выберите то, что применимо):
    • Хеширует только имя записи всех записей в дереве каталогов
    • Хэшируйте содержимое файла всех записей (оставляя мета-подобие, номер инода, ctime, atime, mtime, размер и т. Д., Вы поняли)
    • Для символической ссылки ее содержимым является имя референта. Хэш или пропустить
    • Следовать или не следовать (разрешенное имя) по символической ссылке при хешировании содержимого записи
    • Если это каталог, его содержимое - это просто записи каталога. При рекурсивном обходе они будут в конечном итоге хешироваться, но следует ли хэшировать имена записей этого уровня, чтобы пометить этот каталог? Полезно в случаях использования, когда требуется хеш-код, чтобы быстро идентифицировать изменение без необходимости глубокого просмотра для хеширования содержимого. Примером может служить изменение имени файла, но остальное содержимое остается тем же, и все они являются довольно большими файлами
    • Хорошо обрабатывать большие файлы (опять же, обратите внимание на оперативную память)
    • Обработка очень глубоких деревьев каталогов (обратите внимание на дескрипторы открытых файлов)
    • Обработка нестандартных имен файлов
    • Как действовать с файлами, которые являются сокетами, каналами / FIFO, блочными устройствами, символьными устройствами? Нужно ли их хешировать?
    • Не обновляйте время доступа к любой записи при обходе, потому что это будет побочным эффектом и непродуктивным (интуитивно понятным?) Для определенных случаев использования.

Это то, что у меня на голове, любой, кто потратил некоторое время, работая над этим, практически поймал бы другие ошибки и угловые случаи.

Вот инструмент , очень мало памяти, который решает большинство случаев, может быть немного грубоват, но очень полезен.

Пример использования и вывод dtreetrawl.

Usage:
  dtreetrawl [OPTION...] "/trawl/me" [path2,...]

Help Options:
  -h, --help                Show help options

Application Options:
  -t, --terse               Produce a terse output; parsable.
  -j, --json                Output as JSON
  -d, --delim=:             Character or string delimiter/separator for terse output(default ':')
  -l, --max-level=N         Do not traverse tree beyond N level(s)
  --hash                    Enable hashing(default is MD5).
  -c, --checksum=md5        Valid hashing algorithms: md5, sha1, sha256, sha512.
  -R, --only-root-hash      Output only the root hash. Blank line if --hash is not set
  -N, --no-name-hash        Exclude path name while calculating the root checksum
  -F, --no-content-hash     Do not hash the contents of the file
  -s, --hash-symlink        Include symbolic links' referent name while calculating the root checksum
  -e, --hash-dirent         Include hash of directory entries while calculating root checksum

Фрагмент дружественного к человеку результата:

...
... //clipped
...
/home/lab/linux-4.14-rc8/CREDITS
        Base name                    : CREDITS
        Level                        : 1
        Type                         : regular file
        Referent name                :
        File size                    : 98443 bytes
        I-node number                : 290850
        No. directory entries        : 0
        Permission (octal)           : 0644
        Link count                   : 1
        Ownership                    : UID=0, GID=0
        Preferred I/O block size     : 4096 bytes
        Blocks allocated             : 200
        Last status change           : Tue, 21 Nov 17 21:28:18 +0530
        Last file access             : Thu, 28 Dec 17 00:53:27 +0530
        Last file modification       : Tue, 21 Nov 17 21:28:18 +0530
        Hash                         : 9f0312d130016d103aa5fc9d16a2437e

Stats for /home/lab/linux-4.14-rc8:
        Elapsed time     : 1.305767 s
        Start time       : Sun, 07 Jan 18 03:42:39 +0530
        Root hash        : 434e93111ad6f9335bb4954bc8f4eca4
        Hash type        : md5
        Depth            : 8
        Total,
                size           : 66850916 bytes
                entries        : 12484
                directories    : 763
                regular files  : 11715
                symlinks       : 6
                block devices  : 0
                char devices   : 0
                sockets        : 0
                FIFOs/pipes    : 0
1 голос
/ 28 марта 2016

Я написал скрипт Groovy для этого:

import java.security.MessageDigest

public static String generateDigest(File file, String digest, int paddedLength){
    MessageDigest md = MessageDigest.getInstance(digest)
    md.reset()
    def files = []
    def directories = []

    if(file.isDirectory()){
        file.eachFileRecurse(){sf ->
            if(sf.isFile()){
                files.add(sf)
            }
            else{
                directories.add(file.toURI().relativize(sf.toURI()).toString())
            }
        }
    }
    else if(file.isFile()){
        files.add(file)
    }

    files.sort({a, b -> return a.getAbsolutePath() <=> b.getAbsolutePath()})
    directories.sort()

    files.each(){f ->
        println file.toURI().relativize(f.toURI()).toString()
        f.withInputStream(){is ->
            byte[] buffer = new byte[8192]
            int read = 0
            while((read = is.read(buffer)) > 0){
                md.update(buffer, 0, read)
            }
        }
    }

    directories.each(){d ->
        println d
        md.update(d.getBytes())
    }

    byte[] digestBytes = md.digest()
    BigInteger bigInt = new BigInteger(1, digestBytes)
    return bigInt.toString(16).padLeft(paddedLength, '0')
}

println "\n${generateDigest(new File(args[0]), 'SHA-256', 64)}"

Вы можете настроить использование, чтобы избежать печати каждого файла, изменить дайджест сообщения, убрать хэширование каталогов и т. Д. Я проверил его по данным теста NIST, и он работает, как и ожидалось. http://www.nsrl.nist.gov/testdata/

gary-macbook:Scripts garypaduana$ groovy dirHash.groovy /Users/garypaduana/.config
.DS_Store
configstore/bower-github.yml
configstore/insight-bower.json
configstore/update-notifier-bower.json
filezilla/filezilla.xml
filezilla/layout.xml
filezilla/lockfile
filezilla/queue.sqlite3
filezilla/recentservers.xml
filezilla/sitemanager.xml
gtk-2.0/gtkfilechooser.ini
a/
configstore/
filezilla/
gtk-2.0/
lftp/
menus/
menus/applications-merged/

79de5e583734ca40ff651a3d9a54d106b52e94f1f8c2cd7133ca3bbddc0c6758
1 голос
/ 29 июля 2015

Еще один инструмент для достижения этой цели:

http://md5deep.sourceforge.net/

Как звучит: как md5sum, но также и рекурсивно, плюс другие функции.

1 голос
/ 13 февраля 2009

Я бы направил результаты для отдельных файлов через sort (чтобы предотвратить просто изменение порядка файлов для изменения хэша) в md5sum или sha1sum, в зависимости от того, что вы выберете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...