6

Is there a way to get shasum to only print the hash?

I know this can be achieved by piping the output to another program, e.g.

shasum something | cut -d' ' -f1

Is there a way to achieve this only using shasum, without having to pipe the result somewhere else?

Armand
  • 363
  • 1
  • 3
  • 9

4 Answers4

2

No. As of Perl shasum 6.02 and the corresponding programs in GNU coreutils 9.1, there is no way to print just the hexadecimal representation of the hash without a file name (which can be - for standard input).

But don't let this be a problem! The shell is designed to combine multiple programs and pipes are a fundamental feature of the shell. You just need to be careful not to swallow the error — this is a design defect with sh pipes.

In plain sh, it's actually easier to use a “hidden” pipe via a command substitution, rather than a shell pipeline.

out=$(shasum <something) && echo "${out%%[!0-9A-Za-z]*}"

Explanation: The first part of the command (before &&) sets out to the output of shasum. Since it's a simple assignment, its status is the status of the single command substitution, so it fails if shasum fails. The && operator ensures that if the left-hand side fails, the whole command fails. If the left-hand side succeeds, the right-hand side prints the leading alphanumerical characters of the output. (… && echo "${out%% *}" would work too, the version above is slightly more robust in case a future version uses a tab for example.)

1

No, shasum always prints the filename of the file that it computes the hash for, or - if it reads from standard input.

To avoid the pipe, you could use

perl -MDigest::SHA -e '$s=Digest::SHA->new(); $s->add(<>); print $s->hexdigest(),"\n"' filename
Kusalananda
  • 333,661
  • Note that the code posted here completely ignores errors. For example it will happily print a checksum and return 0 if the specified file doesn't exist. This is an annoyance with perl for system programming. – Gilles 'SO- stop being evil' Jul 26 '22 at 19:21
1

FWIW, the ast-open of sha1sum (or cksum -x sha1) which can also be the sha1sum builtin of ksh93 if built as part of ast-open (enabled there with builtin sha1sum or by putting /opt/ast/bin ahead of $PATH), or the sha1 utility as found for instance on FreeBSD, only prints the checksum when summing stdin.

So, with those implementation, you can just do:

sha1sum < thefile
sha1 < thefile
$ ./ast-open/arch/linux.i386-64/bin/ksh
$ builtin sha1sum
$ whence -a sha1sum
sha1sum is a shell builtin
sha1sum is a shell builtin version of /usr/bin/sha1sum
$ echo test | sha1sum
4e1243bd22c66e76c2ba9eddc1f91394e57f9f83
$ echo test | /usr/bin/sha1sum
4e1243bd22c66e76c2ba9eddc1f91394e57f9f83  -

openssl sha1 can also print the checksum raw, which you can convert to hex with hexdump -e '20/1 "%02x" "\n"' or xxd -p for instance:

openssl sha1 -binary -- "$file" | xxd -p

The GNU implementation of sha1sum outputs <thehexsum> - (the second space possibly replaced with * to indicate binary mode on MSDOS-like systems), same for the shasum utility shipped with perl. openssl sha1 outputs (stdin)= <thehexsum>, openssl sha1 -r (-r meant to emulate GNU coreutils format) outputs <thehexsum> *stdin

So, as already said, with those, you'd have to extract the checksum from that:

sha1sum < "$file" | awk '{print $1}'

(with set -o pipefail beforehand where supported to preserve sha1sum (or file input redirection) failure if any)

Or, in POSIX-like shells:

sum=$(sha1sum < "$file") && sum=${sum%%[[:space:]]*}

[[:space:]]* can also be replaced with [![:xdigit:]]* to remove everything starting with the first character that is not a hexadecimal digit.

-1

You can use cut command anyway

  1. without piping into cut
$ sha256sum ~/hwinfo.txt
d7e1653cc9e37552a70a9daebefdc3bc25949a691086cd325d071a98dfc105aa  /home/user/hwinfo.txt

2.piping into cut while using space as a delimetere

$ sha256sum ~/hwinfo.txt | cut -d" " -f 1
d7e1653cc9e37552a70a9daebefdc3bc25949a691086cd325d071a98dfc105aa

There are 3 fields

field 1 is sha256sum

$ sha256sum ~/hwinfo.txt | cut -d" " -f 1
d7e1653cc9e37552a70a9daebefdc3bc25949a691086cd325d071a98dfc105aa

field 2 is empty because here nothing is in between two spaces

$ sha256sum ~/hwinfo.txt | cut -d" " -f 2

field 3 is the file name

$ sha256sum ~/hwinfo.txt | cut -d" " -f 3
/home/user/hwinfo.txt
  • If you do string processing on the output, counting the characters is a really bad way to do it. Just take all the characters up to the first space. This does use a pipe though (not a shell pipeline, but the command substitution does use a pipe). – Gilles 'SO- stop being evil' Jul 26 '22 at 19:15
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center. – Community Aug 04 '22 at 15:38