Use bash
redirection and process substitution to programmatically distinguish standard error from regular output.
The idea
The idea is to prepend each line of output with a custom pattern using process substitution.
$ du -hs /var/log 2> >(awk '{print "[STDERR] " $0}') 1> >(awk '{print "[STDOUT] " $0}') [STDERR] du: cannot read directory '/var/log/couchdb': Permission denied [STDERR] du: cannot read directory '/var/log/redis': Permission denied [STDERR] du: cannot read directory '/var/log/gdm3': Permission denied [STDERR] du: cannot read directory '/var/log/speech-dispatcher': Permission denied [STDERR] du: cannot read directory '/var/log/samba/cores': Permission denied [STDOUT] 2.6G /var/log
This way, you can use a custom output format according to your needs.
$ find /etc -name fstab 2> >(awk '{print "[\033[1;31mSTDERR\033[0m] " $0}') 1> >(awk '{print "[\033[1;34mSTDOUT\033[0m] " $0}') [STDERR] find: '/etc/ssl/private': Permission denied [STDERR] find: '/etc/polkit-1/localauthority': Permission denied [STDERR] find: '/etc/libvirt/secrets': Permission denied [STDERR] find: '/etc/ipsec.d/private': Permission denied [STDERR] find: '/etc/lvm/backup': Permission denied [STDERR] find: '/etc/lvm/archive': Permission denied [STDERR] find: '/etc/cups/ssl': Permission denied [STDERR] find: '/etc/vpnc': Permission denied [STDOUT] /etc/fstab
Usage scenario #1
export
redirections to the environment variable and use eval
builtin command to read and concatenate it together into a single command.
$ export distinguish_output="2> >(awk '{print \"[\033[1;31mSTDERR\033[0m] \" \$0}') 1> >(awk '{print \"[\033[1;34mSTDOUT\033[0m] \" \$0}')" $ eval df -h / $distinguish_output [STDOUT] Filesystem Type Size Used Avail Use% Mounted on [STDOUT] /dev/mapper/ubuntu--vg-root ext4 232G 161G 59G 74% /
You can define this variable inside ~/.bashrc
file to use it later.
Usage scenario #2
You can use exec
builtin command to alter existing redirections.
$ (exec 2> >(awk '{print "[\033[1;31mSTDERR\033[0m] " $0}') 1> >(awk '{print "[\033[1;34mSTDOUT\033[0m] " $0}'); touch /etc/sudoers.d/local)
[STDERR] touch: cannot touch '/etc/sudoers.d/local': Permission denied
Remember to execute the command in a sub-shell. Trust me, you do not want to mess with current shell redirections.
Usage scenario #3
For simple use cases, define a custom shell function.
$ function distinguish_out { ( exec 2> >(awk '{print "[\033[1;31mSTDERR\033[0m] " $0}') 1> >(awk '{print "[\033[1;34mSTDOUT\033[0m] " $0}'); eval $*; ) } $ distinguish_out find /var/log -name syslog [STDERR] find: '/var/log/couchdb': Permission denied [STDERR] find: '/var/log/redis': Permission denied [STDERR] find: '/var/log/gdm3': Permission denied [STDERR] find: '/var/log/speech-dispatcher': Permission denied [STDERR] find: '/var/log/samba/cores': Permission denied [STDOUT] /var/log/installer/syslog [STDOUT] /var/log/syslog
You can create an alias and store it alongside the preceding function inside ~/.bashrc
file.
Additional notes
I cannot guarantee the order in which the standard output and error are printed to the screen.