4

I have a script that returns the sha1sum of each file in a directory along with the full path of the file.

for i in /path/to/directory*.*; do sha1sum $i >> checksums.txt; done

Returns:

sha1sum  /path/to/directory/filename
sha1sum  /path/to/directory/filename2
sha1sum  /path/to/directory/filename3

How can I modify this such that the output contains only the sha1sum and the filename. I do not want to print the full path of the file.

I figure using sha1sum $i | awk '{print $1}' is the way to go but I do not know how to get only the file name

4

IMHO the simplest approach would be to change to the directory first, in a subshell:

(cd /path/to/directory ; for i in *.*; do sha1sum "$i" ; done) >> checksums.txt

Note that *.* only matches files with a 'dot extension' - to checksum all files, just use *


If you choose to go the awk route, then one approach would be to substitute the longest substring up to a / of the second field:

for i in /path/to/directory/*.*; do sha1sum $i ; done | awk '{sub(/.*\//,"",$2)} 1' >> checksums.txt
  • Yea. This worked. Should have taken the simple route way earlier. – user627497 Jan 2 '17 at 23:34
  • Instead of using a loop I would just use sha1sum *.*. It is simpler and you don't get problems if you forget the quotes in "$i". – kasperd Jan 3 '17 at 7:58
  • @kasperd yes - good point – steeldriver Jan 3 '17 at 13:40
2

Just use find command with -exec flag like so:

$ find ./TESTDIR -type f -printf "%f\t" -exec bash -c 'sha256sum "$@" | awk "{print \$1}"' sh "{}" \; 
out.txt cc29e205d04a4062d0fb131700e8bfc8e54c44d0176a8dca22f40b24ef26d325
2.txt   f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2
with space.txt  e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
script.pl   e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
3.txt   f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2
steam_locomotive    e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
storm carl  e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
1.txt   f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2
sal e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
simple_curl e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

The way this works is that we're just printing basename first with -printf "%f\t" flag, and execute shell inside -exec flag with passing actual file path as command-line argument to the shell itself.

While this looks slightly complex , this works on arbitrary path passed to find command, thus no need to cd around filesystem

Better formatting can be achieved with a variation of the command above, which reverses position of -printf and -exec flags:

$ find ./TESTDIR -type f -exec bash -c "sha256sum '{}' | awk '{printf  \"%s\t\",\$1}' " \; -printf "%f\n"
cc29e205d04a4062d0fb131700e8bfc8e54c44d0176a8dca22f40b24ef26d325    out.txt
f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2    2.txt
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855    with space.txt
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855    script.pl
f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2    3.txt
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855    steam_locomotive
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855    storm carl
f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2    1.txt
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855    sal
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855    simple_curl

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy