TransWikia.com

How to conditionally redirect the output to files based on variable in bash

Unix & Linux Asked by Raywando on October 31, 2021

I’m trying to use eval command to eval a comment — I’m not sure if this is the right way to do it. Example:

i=?? (What I want here is either a #, to comment what’s after, or blank)

somecommand arg1 arg2 $(eval $i) >> file

So based on the $i value it has to be either:

somecommand arg1 arg2 # >> file as of "Don’t print to file"

or

somecommand arg1 arg2 >> file as of "Print to file"

An example script for more clarity:

i=true

somecommand arg1 arg2 >> file1
[some code]
somecommand arg1 arg2 >> file2
[some code]
somecommand arg1 arg2 >> file3
[some code]
And so on...

I want it to print the output to the files only if $i it true; or, as I tried at first, to eval the $i to be a comment and comment the ‘output to file’ piece of code.

I asked because I think there is a more elegant way than doing something like this:

if $i
then
   somecommand arg1 arg2 >> file3
else
   somecommand arg1 arg2
fi

One Answer

You could always do:

unset -v log
# or
log=true
([ -z "$log" ] || exec >> file1; somecommand arg1 arg2)
([ -z "$log" ] || exec >> file2; somecommand arg1 arg2)

Or:

if [ -n "$log" ]; then
  exec 3>> file1 4>> file2
else
  exec 3>&1 4>&1
fi
somecommand arg1 arg2 >&3
somecommand arg1 arg2 >&4

Or:

log() {
  local output="$1"; shift
  if [ -n "$output" ]; then
    "$@" >> "$output"
  else
    "$@" 
  fi
}

log "${log+file1}" somecommand arg1 arg2
log "${log+file2}" somecommand arg1 arg2

Or (make sure the data passed to eval is not dynamic to avoid code injection vulnerabilities, hence the use of single quotes below inside which no expansion occurs):

eval ${log+'>> file1'} 'somecommand arg1 arg2'
eval ${log+'>> file2'} 'somecommand arg1 arg2'

With zsh:

if (($+log)); then
  alias -g 'log?=>>'
else
  alias -g 'log?=#'
fi

somecommand arg1 arg2 log? file1
somecommand arg1 arg2 log? file2

Or even (if you don't intend to use >> for anything other than that kind of conditional logging):

(($+log)) || alias -g '>>=#'

somecommand arg1 arg2 >> file1
somecommand arg1 arg2 >> file2

bash doesn't have alias -g, doesn't let you alias things like >>, but you could use simple aliases if you move the redirection to the start:

shopt -s expand_aliases
skip_one() { shift; "$@"; }
if [[ -v log ]]; then
  alias 'log?=>>'
else
  alias 'log?=skip_one'
fi

log? file1 somecommand arg1 arg2
log? file2 somecommand arg1 arg2

Answered by Stéphane Chazelas on October 31, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP