I would like to have a logging function that takes filenames as arguments and replicate the stdout to all of these files. This is what I have come up so far:
function logger() {
exec > >(tee -ia /var/log/{log1,log2})
}
When I try to replace {log1,log2}
with {$*}
, I get the arguments separated by space. So, I thought I would do something like this:
function logger() {
exec > >(IFS=,; tee -ia /var/log{"$*"}
}
This fails to do what I want as brace expansion happens before moving on to the variable substitution. So, I thought I could do this:
function logger() {
exec > >(IFS=,; eval "tee -ia /var/log/\{$*\}")
}
But this behaves the same, ie logger one two
creates one single file named {one,two}
.
Why is that? How can I get brace expansion to work so that tee
writes to multiple files?
You can't use variable in a brace expansion in bash
. See e.g. How can I use $variable in a shell brace expansion of a sequence?
If you don't want to call your logger
function as
logger /var/log/log{1,2}
with the function written as
logger () {
exec > >( tee -ia "$@" )
}
then what you could do is call it as
logger log{1,2}
or
logger log1 log2
and write the function as
logger () {
for fname do
set -- "$@" "/var/log/$fname"
shift
done
exec > >( tee -ia "$@" )
}
or shorter (but more or less unreadable),
logger () {
set -- "${@/#//var/log/}"
exec > >( tee -ia "$@" )
}
or, if you wish,
logger () {
exec > >( tee -ia "${@/#//var/log/}" )
}
This rewrites each element of the list of positional parameters by adding /var/log/
to the beginning of each of them. tee
is then invoked with the list of modified arguments.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments