19

Is it possible to have SHA sums print without the - appended to the end?

$ echo test | sha1sum 
4e1243bd22c66e76c2ba9eddc1f91394e57f9f83  -  <--- this "-" dash/hyphen

I know we can use awk and other command line tools, but can it be done without using another tool?

$ echo test | sha1sum | awk '{print $1}'
4e1243bd22c66e76c2ba9eddc1f91394e57f9f83
Rui F Ribeiro
  • 55,929
  • 26
  • 146
  • 227
user325067
  • 193
  • 1
  • 1
  • 5

6 Answers6

14

Since sha1sum hashes are 40 characters long, you could pipe the output into a head command and pull the first 40 characters from it:

echo test | sha1sum | head -c 40

Source: https://stackoverflow.com/a/14992739/4642023

Joe Maffei
  • 241
  • 2
  • 3
  • 4
    Alternatively, you can cut at the space with `echo test | sha1sum | cut -f 1 -d " "`. Same result, but you don't have to count characters. – krs013 May 26 '21 at 22:09
8

This is not possible without another tool or without editing the actual sha1sum script/binary. When sha1sum is fed a file it prints the filename after the sum. When sha1sum is not fed a file or is used with a pipe. It puts the - there as a placeholder to indicate that the input was not a file.

Michael Prokopec
  • 2,202
  • 7
  • 21
  • 8
    The `-` actually represents `stdin`. From `man md5sum` *With no FILE, or when FILE is -, read standard input.* –  Dec 10 '18 at 08:14
5

in bash, no extra tools.

h=($(echo test | sha1sum )) ;echo $h 

4e1243bd22c66e76c2ba9eddc1f91394e57f9f83

or

 h=( `echo test | sha1sum` ) ;echo $h 

In bash this uses the "Array" declaration of h creating an multiindex array of tokens. referencing the variable again with as $h an index array is the same as ${h[0]}

using basic shell substitution

 h=`echo test | sha1sum` ;echo ${h// */} 

or posix shell (sh, dash, bash) to drop a suffix with %

h=`echo test | sha1sum` ;echo ${h%-}

may also succeed though using the arrays is imho a more intuitive choice.

adding base64

xxd + base64 can be used to increase the entropy (reduce the number of bits) in printable character ranges

 h=($(echo test | sha1sum )) ;echo $h|xxd -r -p |base64
ThJDvSLGbnbCup7dwfkTlOV/n4M=
4

Newline

Understand that the echo is adding a newline at the end which changes the hash:

 $ echo test | sha1sum
 4e1243bd22c66e76c2ba9eddc1f91394e57f9f83  -

 $ echo -n test | sha1sum
 a94a8fe5ccb19ba61c4c0873d391e987982fbbd3  -

Answer

But no, there is no way to make sha1sum to print only the hash. The reason is that the line is actually an encoded string. The line could start with a \ and the second space (yes, there are two) between the hash and the filename could become a * to indicate a binary hash (useful in DOS):

 $ echo "hello" >'a\file'
 $ md5sum -b 'a\file'
 \b1946ac92492d2347c6235b4d2611184 *a\\file

So, no, it is not a good idea to try to parse that output without understanding the above.


Alternatives

A couple of simpler solutions on other languages are:

 $ echo "test" | perl -le 'use Digest::SHA qw(sha1_hex); print sha1_hex(<>);'
 4e1243bd22c66e76c2ba9eddc1f91394e57f9f83

Or (for longer input, less memory used), write to a file (lets call it sha1.perl):

 use Digest::SHA qw(sha1_hex);
 $state = Digest::SHA->new(sha1);
 for (<>) { $state->add($_) }
 print $state->hexdigest, "\n";

Execute it:

 $ echo "test" | perl sha1.perl 
 4e1243bd22c66e76c2ba9eddc1f91394e57f9f83

 $ echo "test" | php -r '$f = fgets(STDIN);  echo sha1($f),"\n";'
 4e1243bd22c66e76c2ba9eddc1f91394e57f9f83

Write this to a file (lets call it sha1.py):

 import hashlib
     m = hashlib.sha1()

 import sys

 for line in sys.stdin:
     m.update(line)

 print m.hexdigest()

Use it:

 $ echo "test" | python sha1.py
 4e1243bd22c66e76c2ba9eddc1f91394e57f9f83
2

Seems odd nobody mentioned this, but I find it easiest to just trim the output using "tr" command. Nothing against bash/perl/python regex, but I could never get them all without googling for 5 minutes.

$ echo -n "hello" | sha256sum | tr -d "\n *-"
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
Fifi Gaia
  • 21
  • 1
1

You can use printf, like

printf `printf test | sha1sum`

Here the inner printf feeds the input into sha1sum. The output of that, which splits nicely into params, is passed as two params to the outer printf, which then prints the first param (which is the hash value)

The advantage of using printf over echo + trying to parse the output into an array is it works the same across most common shells like bash, bash (in sh-compatibility mode), zsh, ksh etc., whereas echo and array behavior vary across those. Also this is done using the shell alone, no other programs needed.

0cd
  • 131
  • 4