I'm trying to write a bash script where every command is passed through a function that evaluates the command using this line:
eval $1 2>&1 >>~/max.log | tee --append ~/max.log
An example of a case where it does not work is when trying to evaluate a cd command:
eval cd /usr/local/src 2>&1 >>~/max.log | tee --append ~/max.log
The part the causes the issue is the | tee --append ~/max.log part. Any idea why I'm experiencing issues?
From the bash(1)
man page:
Each command in a pipeline is executed as a separate process (i.e., in a subshell).
Therefore, cd
can not change the working directory of the current shell when used in a pipeline. To work around this restriction, the usual approach would be to group cd
with other commands and redirect the output of the group command:
{
cd /usr/local/src
command1
command2
} | tee --append ~/max.log
Without breaking your existing design, you could instead handle cd
specially in your filter function:
# eval all commands (will catch any cd output, but will not change directory):
eval $1 2>&1 >>~/max.log | tee --append ~/max.log
# if command starts with "cd ", execute it once more, but in the current shell:
[[ "$1" == cd\ * ]] && $1
Depending on your situation, this may not be enough: You may have to handle other commands that modify the environment or shell variables like set
, history
, ulimit
, read
, pushd
, and popd
as well. In that case it would probably be a good idea to re-think the program's design.