3
\$\begingroup\$

just a little script, or a bit of a template of one that I used to submit an assignment.
I believe it all works fine, I just wanted to give it to other people, and get some feedback on it; maybe make some improvements. I have several variations of the main check_hash function. I've included two of them here today and it's the main element that I'd like some feedback on. Not necessarily just for the sake of this one script, but more to help me design/write better scripts in the future.

I couldn't really decide if I ought to hardcode the variables in place (like variation #1), or make them more modular and have the take arguments (like variation #2). You can have static values like I have here, or you could read values in to the script or accept positional parameters or adapt it however you like.

Some bits have been commented out. I just used them while testing bits and pieces, and thought i'd leave them there for quick debugging in the future. You probably want to know about md5 vs md5sum: I was taking a class on on Unix & C Programming, where we use a bunch of different UNIX-based systems. Some (macOS, most notably), don't have a native md5sum utility, but they have a similar utility just called md5. So that's all that is.

It's not really supposed to be some kind of security / protection mechanism, It's more just to verify file integrity and ensure it's not corrupt.

preamble

#!/usr/bin/env bash

directory='2CvAwTx'
tarball="$directory.tar.gz"
md5='135c72bc1e201819941072fcea882d6f'
sha='318e96fd35806cd008fe79732edba00908fcbeff'

check_hash function

variant #1

################################################################################
check_hash ()
{
    ############################################################################
    check_md5 () 
    { 
        if [[ "$(command -v md5)" ]];
            then [[ "$(md5 ./"$tarball" | awk '{print $4}')" == "$md5" ]] ;
        elif [[ "$(command -v md5sum)" ]];
            then [[ "$(md5sum ./"$tarball" | awk '{print $1}')" == "$md5" ]] ;
        fi
    }
    ############################################################################
    check_sha ()
    {
        [[ "$(shasum ./"$tarball" | awk '{print $1}')" == "$sha" ]] ;
    }
    ############################################################################
    check_md5 "$@" ||
    check_sha "$@" ;
}
################################################################################
# check_hash &&
#     printf '%s\n' 'true' ||
#     printf '%s\n' 'false' ;

variant #2

################################################################################
check_hash ()
{
    ############################################################################
    check_md5 () 
    {
        if [[ "$(command -v md5)" ]] ;
            then read -r hash _ < <(md5 -q "$1") ;
            [[ $hash == "$2" ]] ;
        elif [[ "$(command -v md5sum)" ]] ;
            then read -r hash _ < <(md5sum "$1") ;
            [[ $hash == "$2" ]] ;
        fi
    }
    ############################################################################
    check_sha ()
    {
        read -r hash _ < <(shasum "$1") ;
        [[ $hash == "$2" ]] ;
    }
    ############################################################################
    check_md5 "$@" || 
    check_sha "$@" ;
}
################################################################################
# check_hash ./"$tarball" "$md5" ||
# check_hash ./"$tarball" "$sha" &&
#     printf '%s\n' 'true' ||
#     printf '%s\n' 'false' ;

the part where the things do the stuff

wget "http://www.example.com/$tarball" &&
check_hash "$tarball" "$md5"           && 
tar -xzf "$tarball"                    &&
cd "$directory"                        &&
make && make clean                     &&
./a.out
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Functions inside of functions have global scope unless you declare the outer one with parens, like func() ( ... ).

You can avoid filenames in the output with < input redirection. md5sum and sha1sum will print - for the filename; testing with a regex allows us to ignore that.

The encompassing logic is "try these things until one works," so just do that.

Putting it all together:

check_hash() { 
     for sum in md5 md5sum shasum
     do 
         [[ $( $sum <"$1" ) =~ ^$2" "*-?$ ]] && return 0 
     done  2>/dev/null
}
\$\endgroup\$
2
  • \$\begingroup\$ I didn't know = is different from ==! Do you have a reference for that? \$\endgroup\$
    – l0b0
    May 25, 2019 at 23:05
  • \$\begingroup\$ turns out that it isn't! I probably got the idea from an old version of the manual where it was worded like they are different: When the '==' and '!=' operators are used, the string to the right of the operator is considered a pattern and matched according to the rules described below / ... / [== means] True if the strings are equal. '=' may be used in place of '==' for strict POSIX compliance. Current manuals make clear that = and == are the same thing. \$\endgroup\$ May 26, 2019 at 6:43

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.