Подтвердить что ты не робот

Linux: вычислить один хэш для данной папки и содержимого?

Конечно, должен быть способ сделать это легко!

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

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

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

sha1sum /folder/of/stuff > singlehashvalue

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

4b9b3361

Ответ 1

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

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 заставят его напечатать имя файла с последующими восьмеричными разрешениями. Два поиска будут выполняться один за другим, вызывая удвоение количества операций ввода-вывода на диске: первый найдет все имена файлов и проверит контрольную сумму, второй найдет все имена файлов и каталогов, имя и режим печати. Список "имен файлов и контрольных сумм", за которым следуют "имена и каталоги с разрешениями", будет затем контрольной суммой для меньшей контрольной суммы.

Ответ 2

  • Используйте инструмент обнаружения вторжений файловой системы, такой как aide.

  • хеш тар-тар из каталога:

    tar cvf -/path/to/folder | sha1sum

  • Напишите что-нибудь самостоятельно, например, vatine oneliner

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

Ответ 3

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

Ответ 4

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

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

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

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

Ответ 5

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

cat $FILES | md5sum

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

cat $(echo $FILES | sort) | md5sum

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

Ответ 6

Для этого существует python script:

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

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

Ответ 7

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

  • Перво-наперво, не забивайте доступную память ! Хеш файл в кусках, а не кормить весь файл.
  • Различные подходы для разных потребностей/целей (все ниже или выберите то, что когда-либо применимо):
    • Хэшировать только имя записи всех записей в дереве каталогов
    • Хэшируйте содержимое файла всех записей (оставляя метаданные, номер инода, 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

Ответ 8

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

Ответ 9

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

http://md5deep.sourceforge.net/

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

Ответ 10

Я написал Groovy script, чтобы сделать это:

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

Ответ 11

Попробуйте сделать это в два этапа:

  • создать файл с хэшами для всех файлов в папке
  • hash этот файл

Так же:

# for FILE in `find /folder/of/stuff -type f | sort`; do sha1sum $FILE >> hashes; done
# sha1sum hashes

Или сделайте все сразу:

# cat `find /folder/of/stuff -type f | sort` | sha1sum

Ответ 12

Вы можете sha1sum сгенерировать список хеш-значений, а затем sha1sum этот список снова, это зависит от того, что именно вы хотите выполнить.

Ответ 13

Я должен был проверить весь каталог для изменений файла.

Но с исключением, отметок времени, владельцев каталогов.

Цель состоит в том, чтобы получить одинаковую сумму где угодно, если файлы идентичны.

В том числе размещены на других машинах, независимо от чего-либо, кроме файлов или изменений в них.

md5sum * | md5sum | cut -d' ' -f1

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

Это намного быстрее, чем метод tar.

Для большей конфиденциальности наших хэшей мы можем использовать sha512sum по тому же рецепту.

sha512sum * | sha512sum | cut -d' ' -f1

Хэши также идентичны везде, где используется sha512sum, но нет никакого известного способа изменить это.

Ответ 14

Вот простой, короткий вариант в Python 3, который отлично работает для небольших файлов (например, дерева исходных текстов или чего-то, где каждый файл может легко помещаться в ОЗУ), игнорируя пустые каталоги, основываясь на идеях других решений:

import os, hashlib

def hash_for_directory(path, hashfunc=hashlib.sha1):                                                                                            
    filenames = sorted(os.path.join(dp, fn) for dp, _, fns in os.walk(path) for fn in fns)         
    index = '\n'.join('{}={}'.format(os.path.relpath(fn, path), hashfunc(open(fn, 'rb').read()).hexdigest()) for fn in filenames)               
    return hashfunc(index.encode('utf-8')).hexdigest()                          

Это работает так:

  1. Найти все файлы в каталоге рекурсивно и отсортировать их по имени
  2. Рассчитать хэш (по умолчанию: SHA-1) каждого файла (считывает весь файл в память)
  3. Создайте текстовый индекс со строками "filename = hash"
  4. Кодировать этот индекс обратно в байтовую строку UTF-8 и хэшировать

Вы можете передать другую хеш-функцию в качестве второго параметра, если SHA-1 не ваша чашка чая.

Ответ 15

Если это git-репо и вы хотите игнорировать любые файлы в .gitignore, вы можете использовать это:

git ls-files <your_directory> | xargs sha256sum | cut -d" " -f1 | sha256sum | cut -d" " -f1

Это хорошо работает для меня.