Reputation: 1169
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
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