Search code examples
bashshellfilegreppiping

How can I access a file in bash and compare its contents with stdout when running a program to make sure they are identical?


How can I to compare the output in stdout of a program with a model output in an output file? I ask because I am trying to make a grading script. Also, I am thinking of using -q grep, but am not sure how I would use it still.

Please make answer simple because I am a noob at bash.

Important edit:

I want to use this in an if statement. For example:

if(modle_file.txt is identical to stdout when running program); then
    echo "Great!"
else
    echo "Wrong output. You loose 1 point."

Edit:

The program takes an input. So for example if we do:

%Python3 Program.py
Enter a number: 5
The first 5 (arbitrary) things are:
2, 5, etc  (program output)

%

Solution

  • If your file is called example.txt, do

    diff example.txt <(program with all its options)
    

    The <() syntax takes the output of the program in parentheses and passes it to the diff command as if it was a text file.

    EDIT:

    If you just want to check whether the text file and the output of the program are the same or not in an if-clause, you can do:

    if [ "$(diff example.txt <(program with all its options))" == "" ]; then
      echo 'the outputs are identical'
    else
      echo 'the outputs differ'
    fi
    

    I.e. diff only generates output if the files differ, so an empty string as answer means the files are identical.

    EDIT 2:

    In principle you can re-direct stdin to a file, like so:

    program < input.txt
    

    Now, without further testing, I don't know whether this will work with your python script, but suppose you can put all the input the program expects into such a file, you could do

    if [ "$(diff example.txt <(program < input.txt))" == "" ]; then
      echo 'Great!'
    else
      echo 'Wrong output. You loose 1 point.'
    fi
    

    EDIT 3::

    I wrote a simple test program in python (let's call it program.py):

    x = input('type a number: ')
    print(x)
    y = input('type another number: ')
    print(y)
    

    If you run it interactively in the shell with python program.py, and give 5 and 7 as answers, you get the following output:

    type a number: 5
    5
    type another number: 7
    7
    

    If you create a file, say input.txt, which contains all the desired input,

    5
    7
    

    and pipe that into your file like so:

    python program.py < input.txt
    

    you get the following output:

    type a number: 5
    type another number: 7
    

    The reason for the difference is that python (and many other shell programs) treat input differently depending on whether it comes from an interactive shell, a pipe, or a redirected stdin. In this case, input is not echoed as the input comes from input.txt. However, if you run both your code and the student's code using input.txt, the two outputs should still be comparable.

    EDIT 4:

    As one of the comments states below, it is not necessary to compare the entire output of the diff command against an empty string ("") if you only want to know whether they differ, the return status is enough. It's best to write a small test script in bash (let's call it code_checker.sh),

    if diff example.txt <(python program.py < input.txt) > /dev/null; then 
        echo "Great!"
    else
        echo "Wrong output. You loose 1 point."
    fi
    

    the >/dev/null part in the if-clause re-directs the output of diff to a special device, effectively ignoring it. If you have a lot of output, it might be better to use cmp like mentioned by user1934428.