Explosion Pills
Explosion Pills

Reputation: 191749

Test whether stdout has been written to

I have a script that prints in a loop. I want the loop to print differently the first time from all other times (i.e., it should print differently if anything has been printed at all). I am thinking a simple way would be to check whether anything has been printed yet (i.e., stdout has been written to). Is there any way to determine that?

I know I could also write to a variable and test whether it's empty, but I'd like to avoid a variable if I can.

Upvotes: 1

Views: 1735

Answers (3)

HashemH
HashemH

Reputation: 1

You cannot use the -f option with %z. The line TMP_SIZE=$(stat -f %z "$TMP") produces a long string that fails the test in if [ $TMP_SIZE -gt 0 ].

Upvotes: 0

TLP
TLP

Reputation: 67900

It's hard to tell what you are trying to do here, but if your script is printing to stdout, you could simply pipe it to perl:

yourcommand | perl -pe 'if ($. == 1) { print "First line is: $_" }'

It all depends on what kind of changes you are attempting to do.

Upvotes: 1

Johannes Weiss
Johannes Weiss

Reputation: 54031

I think that will do what you need. If you echo something between # THE SCRIPT ITSELF and # END, THE FOLLOWING DATA HAS BEEN WRITTEN TO STDOUT will be printed STDOUT HAS NOT BEEN TOUCHED else...

#!/bin/bash

readonly TMP=$(mktemp /tmp/test_XXXXXX)

exec 3<> "$TMP"   # open tmp file as fd 3
exec 4>&1         # save current value of stdout as fd 4
exec >&3          # redirect stdout to fd 3 (tmp file)

# THE SCRIPT ITSELF

echo Hello World

# END

exec >&4          # restore save stdout
exec 3>&-         # close tmp file

TMP_SIZE=$(stat -f %z "$TMP")
if [ $TMP_SIZE -gt 0 ]; then
    echo "THE FOLLOWING DATA HAS BEEN WRITTEN TO STDOUT"
    echo
    cat "$TMP"
else
    echo "STDOUT HAS NOT BEEN TOUCHED"
fi

rm "$TMP"

So, output of the script as is:


THE FOLLOWING DATA HAS BEEN WRITTEN TO STDOUT

Hello World

and if you remove the echo Hello World line:

STDOUT HAS NOT BEEN TOUCHED

And if you really want to test that while running the script itself, you can do that, too :-)

#!/bin/bash

#FIRST ELSE
function echo_fl() {
    TMP_SIZE=$(stat -f %z "$TMP")
    if [ $TMP_SIZE -gt 0 ]; then
        echo $2
    else
        echo $1
    fi  
}

TMP=$(mktemp /tmp/test_XXXXXX)

exec 3 "$TMP"   # open tmp file as fd 3
exec 4>&1         # save current value of stdout as fd 4
exec >&3          # redirect stdout to fd 3 (tmp file)

# THE SCRIPT ITSELF

for f in fst snd trd; do
    echo_fl "$(echo $f | tr a-z A-Z)" "$f"
done

# END

exec >&4          # restore save stdout
exec 3>&-         # close tmp file

TMP_SIZE=$(stat -f %z "$TMP")
if [ $TMP_SIZE -gt 0 ]; then
    echo "THE FOLLOWING DATA HAS BEEN WRITTEN TO STDOUT"
    echo
    cat "$TMP"
else
    echo "STDOUT HAS NOT BEEN TOUCHED"
fi

rm "$TMP"

output is:

THE FOLLOWING DATA HAS BEEN WRITTEN TO STDOUT

FST
snd
trd

as you can see: Only the first line (FST) has caps on. That's what the echo_fl function does for you: If it's the first line of output, if echoes the first argument, if it's not it echoes the second argument :-)

Upvotes: 1

Related Questions