Reputation: 3860
My program is sending characters-colored text to some log file:
echo -e "\\033[38;5;2m-->\\033[0m Starting program." | tee $LogFile -a
Resulting in a perfectly colored log line, but I would like to simultaneously create another logfile without ANSI codes, due to I need to browse this log in Windows (I know there are some ANSI browsers for Windows, but I prefer to browse the log files using Total Commander, that has no decent plugin for that).
So, I need three outputs in my log line:
--> Starting program.
line to screen.--> Starting program.
line to the logfile with ANSI codes.--> Starting program.
line to the logfile (supposedly without ANSI codes, or so I think).The above line was fine thanks to the tee
command, that solves points 1 and 2, but I don't know how to add some option to save to another file but without ANSI codes, at least without replicating the full line.
Maybe using redirectors, file descriptor, with the help of mkfifo?
My workaround for now is, by the way, duplication of outputs (what becomes a bit awkward):
echo -e "\\033[38;5;2m--> Starting program.\\033[0m" | tee $LogFile -a
echo "--> Starting program." >> $NotANSILogFile
Upvotes: 2
Views: 1162
Reputation: 113864
To send the ansi codes to a log file, ansi.log
, and to the screen, while also sending a non-ansi version to a log file called nonansi.log
, use:
echo -e "\\033[38;5;2m-->\\033[0m Starting program." | tee -a ansi.log | tee /dev/tty | sed $'s/\E[^m]*m//g' >>nonansi.log
tee -a ansi.log
The first tee
command appends the ansi-encoded string the the log file ansi.log
.
tee /dev/tty
The second tee
command sends the ansi-encoded string to the screen. (/dev/tty
is the file name of the current screen.)
sed $'s/\E[^m]*m//g' >>nonansi.log
The final command, sed
removes the ansi sequences and the result is appended to nonansi.log
.
The sed
command is contained in a bash
$'...'
string so that the escape character can be represented simply as \E
. This substitute command looks for sequences that start with escape, \E
, and end with m
and removes them. The final g
tells sed
to perform this substitution on every escape sequence on the line, not just the first one.
If you have GNU sed
, an alternative is to use GNU's \o
notation instead:
sed 's/\o033[^m]*m//g' >>nonansi.log
If you have neither GNU sed
nor bash
, then you need to see what facilities your sed
or your shell provide for the Esc character.
If you need to make multiple log entries, it might be easiest to create a shell function, logger
, to hold all the messy details:
logger() { echo -e "$*" | tee -a ansi.log | tee /dev/tty | sed $'s/\E[^m]*m//g' >>nonansi.log; }
With this function defined, then any log entry can be performed by providing the ansi-encoded string as an argument:
logger "\\033[38;5;2m-->\\033[0m Start."
Upvotes: 3
Reputation: 3860
This method works (needs perl
installed) to send output to screen (ANSI) and two files: $LogFile
(ANSI) and $LogFile.plain
(ANSI-free):
echo -e "\\033[38;5;2m--> Starting program.\\033[0m" | tee >(perl -pe 's/\e\[?.*?[\@-~]//g'>>"$LogFile".plain) $LogFile -a
Details:
tee
command splits output to both screen(stdout) and to the perl
command.perl
line filters the ANSI codes.perl
is redirected to the plain Non-ANSI log file (used LogFile.plain
for its filename).To send output only to files (not to screen) do (same with just a classic >/dev/null
).
echo -e "\\033[38;5;2m--> Starting program.\\033[0m" | tee >(perl -pe 's/\e\[?.*?[\@-~]//g'>>"$LogFile".plain) $LogFile -a >/dev/null
Notes:
>>
instead of >
, as expected for an incremental log file.-a
for the tee
command for the same reason above.sed
instead of perl
, but all the sed
examples I have found until now do not work. If someone knows, please report.Upvotes: 2