How can you override function redirection in bash?

I recently discovered some bash code that used a little-known (well, little-known to me anyway) function redirection function, such as a much simplified one:

 function xyzzy () { echo hello } >/dev/null 

When you call a function using simple xyzzy , it automatically applies the redirects associated with the function, regardless of what you did when you called it.

What I would like to know is if there is a way to override this behavior in a function call to see how the message is generated. I am restrained to modify a file containing all the functions, because (1) it is large, (2) it changes regularly and (3) it is strongly protected by the group that supports it.

I tried:

 xyzzy >&1 

to try to override it, but the output is still not displayed (perhaps because >&1 can be considered no-op).


In other words, given the script:

 function xyzzy () { echo hello } >/tmp/junk rm -f /tmp/junk echo ================ echo Standard output echo ---------------- xyzzy # something else here echo ================ echo Function capture echo ---------------- cat /tmp/junk echo ================ 

currently issues:

 ================ Standard output ---------------- ================ Function capture ---------------- hello ================ 

What can I change to call xyzzy to get hello printed in the standard output section and not in the function capture section?

And that should be without trying to read the /tmp/junk file after it was created, since the actual redirects can be in /dev/null , so they won't be in the file.

+6
source share
2 answers

The only thing I can think of is to parse the output of declare -f function_name and remove the redirect.

This is perhaps the easiest approach. Please note that you need to configure awk script to a specific function layout and not change the function body at all. This means that you can disable redirection only at the top level. You can change all function call trees to disable redirection, but this requires a bash parser that can recognize and modify function calls inside the body.

The following script shows how to do this with your select function. The entire awk command creates a new function, my_xyzzy , which reflects the my_xyzzy function, except for the last line, effectively turning it into:

 function my_xyzzy () { echo hello } 

And the full script by specs:

 function xyzzy () { echo hello } >/tmp/qqqq declare -f xyzzy | awk ' NR==1 {print "my_xyzzy ()"} NR==2 {prev=$0} NR>2 {print prev;prev=$0} END {print "}"}' >$$.bash . $$.bash rm -f $$.bash rm -f /tmp/qqqq echo ================ echo Standard output echo ---------------- my_xyzzy echo ================ echo Function capture echo ---------------- cat /tmp/qqqq echo ================ 

Result:

 ================ Standard output ---------------- hello ================ Function capture ---------------- cat: /tmp/qqqq: No such file or directory ================ 
+2
source

I don’t think that the redirection of Bash functions can be redefined dynamically in the function call, although a temporarily changed shell context can be used by combining Bash aliases and functions (see Magic aliases: layered loophole in the Bourne shell ).

Non-dynamically, this is the last redirection expression, i.e. e. the rightmost one, which cancels the previous ones if the redirection expressions refer to the same file descriptor.

 # example ls -ld / no_such_file 1>/dev/null 1>/dev/tty 1>&2 1>redirtest.txt cat redirtest.txt 

Therefore, glenn jackman's suggestion to use declare -f function_name similar to a way to add the final stdout redirection expression to override the previous ones.

 xyzzy() { echo 'Hello, world!'; } 1>/dev/null #func="$(declare -f xyzzy) 1>&2" func="$(declare -f xyzzy) 1>/dev/tty" eval "$func" xyzzy 
0
source

Source: https://habr.com/ru/post/950500/


All Articles