Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to use `script` with shell functions? (colorized output)

Tags:

bash

shell

I'm using a script to run several tests (npm, python etc...)

These have colored outputs.

I'm actually running some of these tests in parallel sending processes in the background, and capturing output in a variable to display when done (as opposed to letting the output come to TTY and having multiple outputs mixed up together).

All works well, but the output is not colored, and I would like to keep the colors. I understand it is because it is not an output to a TTY so color is stripped, and I looked for tricks to avoid this.

This answer: Can colorized output be captured via shell redirect?

offers a way to do this, but doesn't work with shell functions

If I do:

OUTPUT=$(script -q /dev/null npm test | cat)
echo -e $OUTPUT

I get the output in the variable and the echo command output is colored.

but if f I do:

function run_test() { npm test; }
OUTPUT=$(script -q /dev/null run_test | cat)
echo -e $OUTPUT

I get:

script: run_test: No such file or directory

If I call the run_test function passing it to script like:

function run_test() { npm test; }
OUTPUT=$(script -q /dev/null `run_test` | cat)
echo -e $OUTPUT

it's like passing the output that is already eval'd without the colors, so the script output is not colored.

Is there a way to make shell functions work with script ?

I could have the script call in the function like:

function run_test() { script -q /dev/null npm run test | cat; }

but there are several issues with that:

  • Sometimes I need to run multiple commands in series, and send that in the background to run in parallel, it becomes messy: I want to wrap sequences in a shell function and run that with script.
  • This would already run the function itself, and return when done. What I want is pass the function to call to another function that runs in the background and logs the output with script.

PS: I also tried npm config set color always to force npm to always output colors, but that doesn't seem to help, plus I have other functions to call that are not all npm, so it would not work for everything anyways.

like image 548
MrE Avatar asked Sep 08 '25 07:09

MrE


1 Answers

You can use a program such as unbuffer that simulates a TTY to get color output from software whose output is actually eventually going to a pipeline.

In the case of:

unbuffer npm test | cat

...there's a TTY simulated by unbuffer, so it doesn't see the FIFO going to cat on its output.

If you want to run a shell function behind a shim of this type, be sure to export it to the environment, as with export -f.


Demonstrating how to use this with a shell function:

myfunc() { echo "In function"; (( $# )) && { echo "Arguments:"; printf ' - %s\n' "$@"; }; }
export -f myfunc
unbuffer bash -c '"$@"' _ myfunc "Argument one" "Argument two"
like image 180
Charles Duffy Avatar answered Sep 10 '25 04:09

Charles Duffy