Linux: คำนวณแฮชเดียวสำหรับโฟลเดอร์และเนื้อหาที่กำหนด?


98

ต้องมีวิธีทำง่ายๆแน่นอน!

ฉันได้ลองใช้แอปบรรทัดคำสั่งของ Linux sha1sumแล้วmd5sumแต่ดูเหมือนว่าจะสามารถคำนวณแฮชของไฟล์แต่ละไฟล์และแสดงรายการค่าแฮชได้หนึ่งรายการสำหรับแต่ละไฟล์

ฉันต้องการสร้างแฮชเดียวสำหรับเนื้อหาทั้งหมดของโฟลเดอร์ (ไม่ใช่แค่ชื่อไฟล์)

ฉันต้องการทำสิ่งที่ชอบ

sha1sum /folder/of/stuff > singlehashvalue

แก้ไข:เพื่อชี้แจงไฟล์ของฉันอยู่ในหลายระดับในแผนผังไดเรกทอรีไม่ใช่ทั้งหมดที่อยู่ในโฟลเดอร์รูทเดียวกัน


1
โดย 'เนื้อหาทั้งหมด' คุณหมายถึงข้อมูลตรรกะของไฟล์ทั้งหมดในไดเร็กทอรีหรือข้อมูลพร้อมกับเมตาในขณะที่มาถึงรูทแฮชหรือไม่? เนื่องจากเกณฑ์การคัดเลือกกรณีการใช้งานของคุณค่อนข้างกว้างฉันจึงพยายามพูดถึงข้อปฏิบัติบางประการในคำตอบของฉัน
6 ก

คำตอบ:


124

วิธีหนึ่งที่เป็นไปได้คือ:

เส้นทาง sha1sum / ถึง / โฟลเดอร์ / * | sha1sum

หากมีแผนผังไดเร็กทอรีทั้งหมดคุณน่าจะดีกว่าถ้าใช้ find และ xargs คำสั่งหนึ่งที่เป็นไปได้คือ

ค้นหา path / to / folder -type f -print0 | เรียง -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จะทำให้มันพิมพ์ชื่อของไฟล์ตามด้วยสิทธิ์ฐานแปด การค้นพบทั้งสองจะทำงานทีละรายการทำให้มี IO ดิสก์เพิ่มขึ้นเป็นสองเท่าครั้งแรกค้นหาชื่อไฟล์ทั้งหมดและตรวจสอบเนื้อหาส่วนที่สองค้นหาชื่อไฟล์และไดเรกทอรีทั้งหมดชื่อและโหมดการพิมพ์ รายการ "ชื่อไฟล์และเช็คซัม" ตามด้วย "ชื่อและไดเร็กทอรีพร้อมสิทธิ์" จะถูกตรวจสอบเพื่อให้มีการตรวจสอบขนาดเล็กลง


2
และอย่าลืมตั้งค่า LC_ALL = POSIX ดังนั้นเครื่องมือต่างๆจึงสร้างเอาต์พุตที่เป็นอิสระจากโลแคล
David Schmitt

2
ฉันพบแมว | sha1sum เร็วกว่า sha1sum อย่างมาก | sha1sum YMMV ลองใช้สิ่งเหล่านี้ในระบบของคุณ: time find path / to / folder -type f -print0 | เรียง -z | xargs -0 sha1sum | sha1sum; เวลาค้นหา path / to / folder -type f -print0 | เรียง -z | xargs -0 แมว | sha1sum
Bruno Bronosky

5
@RichardBronosky - สมมติว่าเรามีสองไฟล์คือ A และ B A มี "foo" และ B ประกอบด้วย "bar was here" ด้วยวิธีการของคุณเราจะไม่สามารถแยกสิ่งนั้นออกจากไฟล์ C และ D สองไฟล์โดยที่ C มี "foobar" และ D มี "อยู่ที่นี่" การแฮชไฟล์ทีละไฟล์แล้วแฮชคู่ "ชื่อไฟล์แฮช" ทั้งหมดเราจะเห็นความแตกต่าง
Vatine

2
ในการทำงานนี้โดยไม่คำนึงถึงเส้นทางไดเร็กทอรี (กล่าวคือเมื่อคุณต้องการเปรียบเทียบแฮชของสองโฟลเดอร์ที่ต่างกัน) คุณต้องใช้พา ธ สัมพัทธ์และเปลี่ยนเป็นไดเร็กทอรีที่เหมาะสมเนื่องจากพา ธ รวมอยู่ในแฮชสุดท้าย:find ./folder -type f -print0 | sort -z | xargs -0 sha1sum | sha1sum
robbles

3
@robbles นั่นถูกต้องและทำไมฉันไม่ใส่ค่าเริ่มต้นให้/กับpath/to/folderบิต
Vatine

26
  • ใช้เครื่องมือตรวจจับการบุกรุกระบบไฟล์เช่นเสนาธิการ

  • แฮชบอล tar ของไดเร็กทอรี:

    tar cvf - /path/to/folder | sha1sum

  • เขียนโค้ดด้วยตัวคุณเองเช่นoneliner ของ vatine :

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


3
+1 สำหรับสารละลายน้ำมันดิน นั่นเป็นวิธีที่เร็วที่สุด แต่การลดลง v. verbosity จะทำให้ช้าลงเท่านั้น
Bruno Bronosky

7
โปรดทราบว่าการแก้ปัญหา tar จะถือว่าไฟล์อยู่ในลำดับเดียวกันเมื่อคุณเปรียบเทียบ ว่าจะขึ้นอยู่กับระบบไฟล์ที่ไฟล์อยู่เมื่อทำการเปรียบเทียบหรือไม่
เลขที่

5
แฮชคอมไพล์ไม่เหมาะสำหรับวัตถุประสงค์นี้เนื่องจากเนื้อหาไฟล์เป็นเพียงส่วนหนึ่งของอินพุตเท่านั้น แม้สำหรับการคอมมิตเริ่มต้นของสาขาแฮชยังได้รับผลกระทบจากข้อความคอมมิตและข้อมูลเมตาของคอมมิตด้วยเช่นเวลาของการคอมมิต หากคุณยอมรับโครงสร้างไดเร็กทอรีเดียวกันหลาย ๆ ครั้งคุณจะได้รับแฮชที่แตกต่างกันทุกครั้งดังนั้นแฮชที่ได้จึงไม่เหมาะสำหรับการพิจารณาว่าไดเร็กทอรีสองไดเร็กทอรีเป็นสำเนาที่แน่นอนของกันและกันโดยการส่งแฮชไปเท่านั้น
Zoltan

1
@Zoltan แฮชคอมไพล์นั้นดีมากถ้าคุณใช้แฮชต้นไม้และไม่ใช่แฮชคอมมิต
ฮอบส์

1
@hobbs คำตอบเดิมระบุว่า "กระทำแฮช" ซึ่งไม่เหมาะกับวัตถุประสงค์นี้อย่างแน่นอน แฮชต้นไม้ดูเหมือนจะเป็นตัวเลือกที่ดีกว่ามาก แต่ก็ยังมีกับดักซ่อนอยู่ สิ่งหนึ่งที่อยู่ในใจของฉันคือการตั้งค่าบิตที่เรียกใช้งานได้ในบางไฟล์จะเปลี่ยนแฮชต้นไม้ คุณต้องออกgit config --local core.fileMode falseก่อนตัดสินใจเพื่อหลีกเลี่ยงปัญหานี้ ฉันไม่รู้ว่ามีข้อแม้แบบนี้อีกหรือไม่
Zoltan

14

คุณทำได้ tar -c /path/to/folder | sha1sum


17
หากคุณต้องการจำลองการตรวจสอบดังกล่าวบนเครื่องอื่น tar อาจไม่ใช่ทางเลือกที่ดีเนื่องจากรูปแบบดูเหมือนจะมีพื้นที่สำหรับความคลุมเครือและมีอยู่ในหลายเวอร์ชันดังนั้น tar บนเครื่องอื่นอาจให้ผลลัพธ์ที่แตกต่างจากไฟล์เดียวกัน
slowdog

2
ความกังวลที่ถูกต้องของ slowdog แต่อย่างไรก็ตามถ้าคุณดูแลเกี่ยวกับเนื้อหาของแฟ้มสิทธิ์ ฯลฯ แต่ไม่ปรับเปลี่ยนเวลาคุณสามารถเพิ่มตัวเลือกเช่นดังนั้น:--mtime tar -c /path/to/folder --mtime="1970-01-01" | sha1sum
Binary Phile

@ S.Lott ถ้าขนาดไดเร็กทอรีใหญ่ฉันหมายถึงถ้าขนาดของไดเร็กทอรีใหญ่มากการ
บีบอัด

13

หากคุณต้องการตรวจสอบว่ามีอะไรเปลี่ยนแปลงในโฟลเดอร์หรือไม่ฉันขอแนะนำสิ่งนี้:

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

มันจะให้แฮชของเอาต์พุต ls ซึ่งประกอบด้วยโฟลเดอร์โฟลเดอร์ย่อยไฟล์การประทับเวลาขนาดและสิทธิ์ เกือบทุกอย่างที่คุณต้องพิจารณาว่ามีอะไรเปลี่ยนแปลงหรือไม่

โปรดทราบว่าคำสั่งนี้จะไม่สร้างแฮชสำหรับแต่ละไฟล์ แต่นั่นคือเหตุผลว่าทำไมจึงควรเร็วกว่าการใช้ find


1
ฉันไม่แน่ใจว่าเหตุใดจึงไม่มีการโหวตเพิ่มขึ้นเนื่องจากความเรียบง่ายของโซลูชัน ใครสามารถอธิบายได้ว่าทำไมสิ่งนี้ถึงไม่ได้ผล?
Dave C

1
ฉันคิดว่ามันไม่เหมาะอย่างยิ่งเนื่องจากแฮชที่สร้างขึ้นจะขึ้นอยู่กับเจ้าของไฟล์การตั้งค่ารูปแบบวันที่ ฯลฯ
Ryota

1
คำสั่ง ls สามารถปรับแต่งให้แสดงผลตามที่คุณต้องการ คุณสามารถแทนที่ -l ด้วย -gG เพื่อละกลุ่มและเจ้าของ และคุณสามารถเปลี่ยนรูปแบบวันที่ด้วยตัวเลือก - สไตล์เวลา โดยทั่วไปตรวจสอบหน้า ls man และดูว่าอะไรเหมาะกับความต้องการของคุณ
Shumoapp

@DaveC เพราะมันไร้ประโยชน์มาก หากคุณต้องการเปรียบเทียบชื่อไฟล์เพียงแค่เปรียบเทียบโดยตรง พวกมันไม่ได้ใหญ่ขนาดนั้น
Navin

7
@Navin จากคำถามยังไม่ชัดเจนว่าจำเป็นต้องแฮชเนื้อหาไฟล์หรือตรวจพบการเปลี่ยนแปลงในทรี แต่ละกรณีมีการใช้งาน ตัวอย่างเช่นการจัดเก็บชื่อไฟล์ 45K ในเคอร์เนลทรีนั้นมีประโยชน์น้อยกว่าแฮชเดียว ls -lAgGR - บล็อกขนาด = 1 - เวลาสไตล์ = +% s | sha1sum ทำงานได้ดีสำหรับฉัน
yashma

5

แนวทางที่แข็งแกร่งและสะอาด

  • สิ่งแรกก่อนอื่นอย่าใช้หน่วยความจำที่มีอยู่ ! แฮ็กไฟล์เป็นชิ้น ๆ แทนที่จะป้อนทั้งไฟล์
  • แนวทางที่แตกต่างกันสำหรับความต้องการ / วัตถุประสงค์ที่แตกต่างกัน (ด้านล่างทั้งหมดหรือเลือกสิ่งที่เคยใช้ได้):
    • แฮชเฉพาะชื่อรายการของรายการทั้งหมดในแผนผังไดเร็กทอรี
    • แฮชเนื้อหาไฟล์ของรายการทั้งหมด (ปล่อยให้ meta เช่นหมายเลขไอโหนด ctime atime mtime ขนาด ฯลฯ คุณจะได้รับแนวคิด)
    • สำหรับลิงก์สัญลักษณ์เนื้อหาคือชื่ออ้างอิง แฮชหรือเลือกที่จะข้าม
    • ทำตามหรือไม่ติดตาม (แก้ไขชื่อ) symlink ในขณะที่แฮชเนื้อหาของรายการ
    • หากเป็นไดเร็กทอรีเนื้อหาจะเป็นเพียงรายการไดเร็กทอรี ในขณะที่การข้ามผ่านแบบวนซ้ำจะถูกแฮชในที่สุด แต่ควรแฮชชื่อรายการไดเร็กทอรีของระดับนั้นเพื่อแท็กไดเร็กทอรีนี้หรือไม่ มีประโยชน์ในกรณีการใช้งานที่จำเป็นต้องใช้แฮชเพื่อระบุการเปลี่ยนแปลงอย่างรวดเร็วโดยไม่ต้องเจาะลึกเพื่อแฮชเนื้อหา ตัวอย่างจะเป็นการเปลี่ยนชื่อไฟล์ แต่เนื้อหาที่เหลือยังคงเหมือนเดิมและเป็นไฟล์ที่มีขนาดใหญ่พอสมควร
    • จัดการไฟล์ขนาดใหญ่ได้ดี (โปรดคำนึงถึง RAM อีกครั้ง)
    • จัดการแผนผังไดเร็กทอรีที่ลึกมาก (คำนึงถึงตัวอธิบายไฟล์ที่เปิด)
    • จัดการชื่อไฟล์ที่ไม่ได้มาตรฐาน
    • วิธีดำเนินการกับไฟล์ที่เป็นซ็อกเก็ตไปป์ / FIFO อุปกรณ์บล็อกอุปกรณ์ถ่าน? ต้องแฮชด้วยหรือไม่?
    • อย่าอัปเดตเวลาการเข้าถึงของรายการใด ๆ ในขณะที่กำลังข้ามผ่านเพราะจะเป็นผลข้างเคียงและต่อต้านการผลิต (ใช้งานง่าย?) สำหรับกรณีการใช้งานบางอย่าง

นี่คือสิ่งที่ฉันมีอยู่บนหัวของฉันใครก็ตามที่ใช้เวลาทำงานกับสิ่งนี้ในทางปฏิบัติจะได้จับ gotchas และกรณีมุมอื่น ๆ

นี่เป็นเครื่องมือที่มีน้ำหนักเบามากสำหรับหน่วยความจำซึ่งส่วนใหญ่อาจมีความหยาบรอบ ๆ ขอบ แต่ก็มีประโยชน์มาก

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
คุณสามารถยกตัวอย่างสั้น ๆ เพื่อรับ sha256 ที่มีประสิทธิภาพและสะอาดของโฟลเดอร์หรือสำหรับโฟลเดอร์ Windows ที่มีไดเร็กทอรีย่อยสามไดเร็กทอรีและไม่กี่ไฟล์ในแต่ละโฟลเดอร์
Ferit

3

หากคุณแค่ต้องการแฮชเนื้อหาของไฟล์โดยไม่สนใจชื่อไฟล์คุณก็สามารถใช้ได้

cat $FILES | md5sum

ตรวจสอบให้แน่ใจว่าคุณมีไฟล์ในลำดับเดียวกันเมื่อคำนวณแฮช:

cat $(echo $FILES | sort) | md5sum

แต่คุณไม่สามารถมีไดเร็กทอรีในรายการไฟล์ของคุณ


2
การย้ายจุดสิ้นสุดของไฟล์หนึ่งไปยังจุดเริ่มต้นของไฟล์ที่ตามตัวอักษรจะไม่ส่งผลต่อแฮช แต่ควร ตัวคั่นไฟล์หรือความยาวของไฟล์จะต้องรวมอยู่ในแฮช
Jason Stangroome

3

เครื่องมืออื่นในการบรรลุเป้าหมายนี้:

http://md5deep.sourceforge.net/

ตามที่เป็นเสียง: เช่น md5sum แต่ยังเรียกซ้ำพร้อมคุณสมบัติอื่น ๆ


1
แม้ว่าลิงก์นี้อาจตอบคำถามได้ แต่ควรรวมส่วนสำคัญของคำตอบไว้ที่นี่และระบุลิงก์เพื่อการอ้างอิง คำตอบแบบลิงก์เท่านั้นอาจไม่ถูกต้องหากหน้าที่เชื่อมโยงเปลี่ยนไป
Mamoun Benghezal

3

หากนี่เป็น git repo และคุณต้องการละเว้นไฟล์ใด ๆ ใน.gitignoreคุณอาจต้องการใช้สิ่งนี้:

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

สิ่งนี้ใช้ได้ดีสำหรับฉัน


ขอบคุณมาก! :)
visortelle

สำหรับการใช้งานจำนวนมากแนวทางนี้ดีกว่า การแฮชไฟล์ซอร์สโค้ดจะได้รับแฮชที่ไม่ซ้ำกันเพียงพอในเวลาที่น้อยลง
John McGehee

2

มีสคริปต์ python สำหรับสิ่งนั้น:

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

หากคุณเปลี่ยนชื่อไฟล์โดยไม่เปลี่ยนลำดับตัวอักษรสคริปต์แฮชจะตรวจไม่พบ แต่ถ้าคุณเปลี่ยนลำดับของไฟล์หรือเนื้อหาของไฟล์ใด ๆ การเรียกใช้สคริปต์จะทำให้คุณมีแฮชที่แตกต่างจากเดิม


2

ฉันต้องตรวจสอบในไดเรกทอรีทั้งหมดสำหรับการเปลี่ยนแปลงไฟล์

แต่มีการยกเว้นการประทับเวลาการเป็นเจ้าของไดเรกทอรี

เป้าหมายคือการได้รับผลรวมที่เหมือนกันทุกที่หากไฟล์เหมือนกัน

รวมถึงโฮสต์ลงในเครื่องอื่น ๆ โดยไม่คำนึงถึงสิ่งใดก็ตามนอกจากไฟล์หรือการเปลี่ยนแปลงไฟล์เหล่านั้น

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

สร้างรายการแฮชตามไฟล์จากนั้นเชื่อมแฮชเหล่านั้นเข้าด้วยกัน

วิธีนี้เร็วกว่าวิธีน้ำมันดิน

เพื่อความเป็นส่วนตัวที่ดียิ่งขึ้นในแฮชของเราเราสามารถใช้sha512sumในสูตรเดียวกัน

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

แฮชยังเหมือนกันทุกที่โดยใช้sha512sumแต่ไม่มีวิธีใดที่ทราบวิธีย้อนกลับ


สิ่งนี้ดูเหมือนจะง่ายกว่าคำตอบที่ยอมรับสำหรับการแฮชไดเร็กทอรี ฉันไม่พบว่าคำตอบที่ยอมรับนั้นเชื่อถือได้ ปัญหาหนึ่ง ... มีโอกาสที่แฮชจะออกมาในลำดับที่แตกต่างกันหรือไม่? sha256sum /tmp/thd-agent/* | sortคือสิ่งที่ฉันกำลังพยายามเพื่อการสั่งซื้อที่เชื่อถือได้จากนั้นก็แฮ็กมัน
thinktt

สวัสดีดูเหมือนว่าแฮชจะเรียงตามลำดับตัวอักษรตามค่าเริ่มต้น คำสั่งที่เชื่อถือได้หมายความว่าอย่างไร คุณต้องจัดระเบียบทั้งหมดนั้นด้วยตัวเอง ตัวอย่างเช่นการใช้ Associative arrays, entry + hash จากนั้นคุณจัดเรียงอาร์เรย์นี้ตามรายการสิ่งนี้จะให้รายการแฮชที่คำนวณตามลำดับการจัดเรียง ฉันเชื่อว่าคุณสามารถใช้วัตถุ json เป็นอย่างอื่นและแฮชวัตถุทั้งหมดได้โดยตรง
NVRM

ถ้าฉันเข้าใจว่าคุณกำลังบอกว่ามันแฮชไฟล์ตามลำดับตัวอักษร ดูเหมือนจะถูกต้อง มีบางอย่างในคำตอบที่ยอมรับข้างต้นทำให้ฉันมีคำสั่งซื้อที่แตกต่างกันเป็นระยะ ๆ ในบางครั้งฉันจึงพยายามทำให้แน่ใจว่าจะไม่เกิดขึ้นอีก ฉันจะยึดติดกับการเรียงลำดับในตอนท้าย ดูเหมือนจะใช้งานได้ ปัญหาเฉพาะกับวิธีนี้เทียบกับคำตอบที่ยอมรับที่ฉันเห็นคือมันไม่ได้จัดการกับโฟลเดอร์ที่ซ้อนกัน ในกรณีของฉันฉันไม่มีโฟลเดอร์ดังนั้นจึงใช้งานได้ดี
thinktt

แล้วls -r | sha256sumไง?
NVRM

@NVRM ลองใช้และตรวจสอบการเปลี่ยนแปลงชื่อไฟล์ไม่ใช่เนื้อหาไฟล์
Gi0rgi0s

1

ลองทำในสองขั้นตอน:

  1. สร้างไฟล์ที่มีแฮชสำหรับไฟล์ทั้งหมดในโฟลเดอร์
  2. แฮชไฟล์นี้

ชอบมาก:

# 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

for F in 'find ...' ...ไม่ทำงานเมื่อคุณมีช่องว่างในชื่อ (ซึ่งคุณมักจะทำในปัจจุบัน)
mivk

1

ฉันจะไพพ์ผลลัพธ์สำหรับแต่ละไฟล์ผ่านsort(เพื่อป้องกันไม่ให้มีการเรียงลำดับไฟล์ใหม่เพื่อเปลี่ยนแฮช) md5sumหรือsha1sumแล้วแต่คุณจะเลือก


1

ฉันได้เขียนสคริปต์ 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

0

คุณสามารถsha1sumสร้างรายการค่าแฮชจากนั้นsha1sumรายการนั้นอีกครั้งขึ้นอยู่กับว่าคุณต้องการทำอะไรให้สำเร็จ


0

นี่คือรูปแบบสั้น ๆ ที่เรียบง่ายใน Python 3 ที่ใช้งานได้ดีสำหรับไฟล์ขนาดเล็ก (เช่นซอร์สทรีหรือบางสิ่งบางอย่างโดยที่ไฟล์แต่ละไฟล์สามารถใส่ลงใน RAM ได้อย่างง่ายดาย) โดยไม่สนใจไดเร็กทอรีว่างตามแนวคิดจากโซลูชันอื่น ๆ :

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 ไม่ใช่ถ้วยชาของคุณ


0

วิธีที่เร็วที่สุดในการทำยังคงเป็นน้ำมันดิน และด้วยพารามิเตอร์เพิ่มเติมหลายตัวเรายังสามารถกำจัดความแตกต่างที่เกิดจากข้อมูลเมตาได้

ในการใช้ tar สำหรับแฮช dir คุณต้องแน่ใจว่าคุณเรียงลำดับเส้นทางระหว่าง tar มิฉะนั้นจะแตกต่างกันเสมอ

tar -C <root-dir> -cf - --sort=name <dir> | sha256sum

ไม่สนใจเวลา

หากคุณไม่สนใจเกี่ยวกับเวลาในการเข้าถึงหรือแก้ไขเวลาให้ใช้สิ่งที่ต้องการ--mtime='UTC 2019-01-01' ตรวจสอบให้แน่ใจว่าการประทับเวลาทั้งหมดเหมือนกัน

ละเว้นความเป็นเจ้าของ

โดยปกติเราจำเป็นต้องเพิ่ม--group=0 --owner=0 --numeric-ownerเพื่อรวมข้อมูลเมตาของเจ้าของ

ละเว้นบางไฟล์

ใช้ --exclude=PATTERN

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.