portabilitytailtac

check whether command has a specific command line option


Is there any way to check whether a command has a specific command line option from shell script?

My use case is tail command. In BSD version of tail, it has -r (reverse) option. This option is not available in GNU version

I can do a check from shell script to use this option only for MacOS, and use tac for Linux. But the problem is people can install GNU version of tail in MacOS too. So the better solution is to check whether the command has -r option.


Solution

  • This is an impossible problem to solve in the general case; what happens if somebody has a different program installed as tail or an alias or shell function that changes its behaviour? You're finding out here that making portable/reliable shell scripts (particularly between very different operating systems) can be quite difficult. You'll have to decide for yourself how to make all these decisions and where you want to draw the line.

    The quick & dirty way would be simply to call tail -r with some known input and see if the output matches what you'd expect. Use that to make a decision about what to do later on in your script. An example (probably not bulletproof):

    #!/bin/bash
    
    INPUT=$(mktemp)
    OUTPUT=$(mktemp)
    COMPARE=$(mktemp)
    
    cat >${INPUT} <<EOF
    1
    2
    3
    EOF
    
    cat >${COMPARE} <<EOF
    3
    2
    1
    EOF
    
    tail -r ${INPUT} >${OUTPUT} 2>&1
    
    cmp -s ${OUTPUT} ${COMPARE}
    if [ $? == 0 ]
    then
        echo "'tail -r' behaves as expected"
    else
        echo "'tail -r' does not behave as expected"
    fi
    
    rm ${INPUT} ${OUTPUT} ${COMPARE}
    

    It outputs as expected on a Mac and Linux machine I just tested.