1

I have a (bash) script I would like to run on two different computers, one is OpenBSD with the program sha256, the other is Ubuntu with sha256sum. What is the best/standard practice to allow the script to handle both cases?

Note that for sha256 vs sha256sum, the other options into the program wouldn't need to be change, but for a different choice of programs, such as wget vs. curl, the other parameters would change too (e.g. wget vs. curl -O). Therefore, the best answer would allow different command line parameters as well depending on which program is available.

One way of fixing the program is to use a variable that changes depending on the exit status of command, hash, or type, as per this SO question

e.g.

SHA_PROGRAM=sha256
command -v "$SHA_PROGRAM"
# If the exit status of command is nonzero, try something else 
if [ "$?" -ne "0" ]; then
    command -v "sha256sum"
    if [ "$?" -ne "0" ]; then
        printf "This program requires a sha256 hashing program, please install one\n" 1>&2
        exit 1
    else
        SHA_PROGRAM=sha256sum
    fi 
fi
$SHA_PROGRAM $MYFILE

But, that way seems a little verbose to me, not to mention the nested if-statement issue.

It could be generalized a bit by using an array of possible commands:

declare -a POSSIBLE_COMMANDS=("sha256" "sha256sum")
SHA_PROGRAM=""
for $OPT in "${POSSIBLE_COMMANDS[@]}"
do
    command -v "$OPT"
    # if the exit status of command is zero, set the command variable and exit the loop
    if [ "$?" -eq "0" ]; then
        SHA_PROGRAM=$OPT
        break
    fi
done 

# if the variable is still empty, exit with an error    
if [ -z "$SHA_PROGRAM" ]; then
    printf "This program requires a sha256 program. Aborting\n" 1>&2
    exit 1
fi

$SHA_PROGRAM $MY_FILE

That way would work too I believe, but I am hoping to get advice from a more experienced, better bash programmer, in case I am missing some better solution (perhaps a clever use of the || operator?).

  • If both platforms have openssl installed, you can just use openssl sha256 in both places and not worry about picking an os-specific program. – larsks Aug 13 '15 at 2:27
  • I realized after writing this question, this question may be better suited for stack overflow. Should I move it? – hilcharge Aug 13 '15 at 2:29
  • openssl sha256 looks good for generating the hash. Is there a related way to check a file with the hashes listed in it. I.e. equivalent to sha256 -c FILE? – hilcharge Aug 13 '15 at 2:34
  • I don't believe openssl provides such an option. – larsks Aug 13 '15 at 2:43
  • for $OPT in ... won't work, remove $. And it's superfluous to use $? just for checking success/failure, simply write if command -v "$OPT"; then. – yaegashi Aug 13 '15 at 2:48
1

As per @yaegashi's comment, the if command -v ...; then ... seems to hit the nail on the head, simple and clear.

Example:

# The SHA_CMD variable can be used to store the appropriate command for later use
SHA_CMD=""
if command -v sha256; then
    SHA_CMD=sha256
elif command -v sha256sum; then 
    SHA_CMD=sha256sum
else 
    printf "This program requires a a sha256 program installed\n" 1>&2
    exit 1
fi 
"$SHA_CMD" "$MY_FILE" > "$MY_FILE.sha"
# Note: if any of the possible sha commands had command line parameters, then the quotes need to be removed from around $SHA_CMD

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.