Will
Will

Reputation: 1169

Saving input before running command bash

I'm trying to save my entered commands and their respective outputs in a file.
What I'm currently doing:

mylog() {
    echo "----------------" >> ${PWD}/cmds.log
    echo "$@" >> ${PWD}/cmds.log
    # read foo # Tried reading the piped value in to
    # echo "$foo" >> ${PWD}/cmds.log
    # MYCMD="${@}"
    # echo "$MYCMD" >> ${PWD}/cmds.log
    "$@" | tee -a ${PWD}/cmds.log
}

It currently functions like: mylog cat file.txt | mylog sort
And the output in cmds.log is:

----------------
cat file.txt
----------------
sort
....
output from cat
...
output from sort
...

What I'd like is:

----------------
cat file.txt
....
output from cat
...
----------------
sort
...
output from sort
...

In the code, you can see I tried using read and following other method described here.
I also tried doing VAR=${@} but this just saved the command twice and doesn't execute it.

Any idea of how I can accomplish my goal?

Slightly related, I'm manually saving the terminals output like this, and not using script because the interactive shell causes lots of escape characters and such to be caught.

Upvotes: 0

Views: 167

Answers (1)

hyperupcall
hyperupcall

Reputation: 973

Your modified script...

#!/usr/bin/env bash

mylog() {
    local output="log"
    
    # This is the key part right here. The 'tac' command here
    # prints stdin in reverse. To do this, it must read _all_
    # of stdin, so it buffers until it reads everything. Of course,
    # we must use two 'tac's so stdin doesn't actually get reversed.
    # You could also use `sponge(1)` here, but that does not come standard
    # on all Linux distributions / MacOS
    local buffer="$("$@" | tac | tac)"

    # Nothing below will be printed until 'buffer' is completely filled with stdin
    {
        echo "----------------"
        echo "$@"
        echo "----------------"
        echo "$buffer"
        echo
    } >> "$output"

    printf "%s" "$buffer" 
}

rm -f log
mylog cat file.txt | mylog sort >/dev/null

The resulting log

----------------
cat file.txt
----------------
bravo
alfa
charlie
delta
echo

----------------
sort
----------------
alfa
bravo
charlie
delta
echo


Upvotes: 1

Related Questions