0

I have a series of directories with sha1sums and md5sums files in. The format of these files is the usual hash space space filename, with one hash/file per line. I want to verify the files and print out the path as well as the filename of corrupt files.

find . -name SHA1SUMS -execdir echo "$PWD" sha1sum --quiet --check SHA1SUMS \; > logfile

(modified from here) gives

./path1/SHA1SUMS
sda2.ntfs-ptcl-img.gz.aa: FAILED
blkdev.list: FAILED
Info-dmi.txt: FAILED
./path2/SHA1SUMS

Whereas I am looking more for a

./path1/sda2.ntfs-ptcl-img.gz.aa: FAILED
./path1/blkdev.list: FAILED
./path2/file: FAILED

type of output.

luusac
  • 3
  • 2
  • Minor point: your sample output seems to come from `find . -name SHA1SUMS -print -execdir 2>/dev/null sha1sum --quiet --check {} \;` (and not from the shown command). – fra-san Oct 14 '20 at 20:28

3 Answers3

0
#! /bin/bash
here=$(pwd)

find . -name SHA1SUMS | while read -r fname; do
    cd "$here" || exit
    dirn=$(dirname "$fname")
    cd "$dirn" || continue
    sha1sum --quiet --check SHA1SUMS 2>&1 | grep " FAILED" | ( echo -n "$dirn/"; cat )
done > logfile

This will break if you have directories containing \n but it would be extremely unlikely.

Artem S. Tashkinov
  • 26,392
  • 4
  • 33
  • 64
0

Try this:

find . -name SHA1SUMS -execdir \
  sh -c 'sha1sum --quiet -c "$@" | sed "s|^|$PWD/|"' - {} +

If the directories really contain |, you can use some other character in the sed substitution, or use awk -v p="$PWD/" "{print p\$0}" instead.

If your paths really contain newlines you need something smarter than this ;-)

0
find . -name SHA1SUMS -exec sh -c '
  cd "${1%/*}" &&
  sha1sum --check --quiet "${1##*/}" 2>/dev/null |
    while IFS= read -r file
    do
      printf "%s\n" "${1%/*}/$file"
    done' sh {} \;

Its output should match the sample shown in your question and it should work with arbitrary paths.

Alternatively, using awk instead of shell features for prepending SHA1SUMS's relative path to each file name:

find . -name SHA1SUMS -exec sh -c '
  cd "${1%/*}" &&
  sha1sum --check --quiet "${1##*/}" 2>/dev/null |
    awk -v pre="${1%/*}" "{ print pre \"/\" \$0 }"' sh {} \;

Note that, depending on its implementation, sha1sum may print altered file names. Specifically, GNU *sum utilities escape some characters1 and, when in check mode, prepend a \ to file names that need escaping, making the path obtained concatenating the relative path of your SHA1SUMS file and a file name printed by sha1sum unsuitable for reuse.

1 The manual (sha1sum's manual refers to that of md5sum) says, generically, "each problematic character".

fra-san
  • 9,931
  • 2
  • 21
  • 42