Skip to main content
Restore to what was originally written, and add the change as a suggestion.
Source Link

None of the usual shells (even zsh) permit pipes with the | operator other than from stdout to stdin. But all Bourne-style shells support file descriptor reassignment (as in 1>&2). So you can temporarily divert stdout to fd 3 and stderr to stdout, and later put fd 3 back onto stdout. If stuff produces some output on stdout and some output on stderr, and you want to apply filter on the error output leaving the standard output untouched, you can use { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1
standard output
more output
standard error

Ksh, bash and zsh support pipes on arbitrary file descriptors, but they work differently: one command is the main command, and you can pipe its input or output into another command. Process substitution runs a command in the background with either its standard input or its standard output connected to a pipe which you can use in a redirection on the main command. Here you want to filter the standard error, so redirect it to an output process substitution, and redirect the output of the filter command back to stderr.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ stuff 2> >(filter >&2)
standard output
more output
standard error

Note that there are two > characters with a space in between: that's 2> to redirect standard output and >(…) to make a process substitution. The space is necessary because 2>>… would be parsed as an append redirection.


To make this approach function like the first part of the answer, redirect the output of the filter command back to stderr:

    ︙
$ stuff 2> >(filter >&2)

None of the usual shells (even zsh) permit pipes with the | operator other than from stdout to stdin. But all Bourne-style shells support file descriptor reassignment (as in 1>&2). So you can temporarily divert stdout to fd 3 and stderr to stdout, and later put fd 3 back onto stdout. If stuff produces some output on stdout and some output on stderr, and you want to apply filter on the error output leaving the standard output untouched, you can use { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1
standard output
more output
standard error

Ksh, bash and zsh support pipes on arbitrary file descriptors, but they work differently: one command is the main command, and you can pipe its input or output into another command. Process substitution runs a command in the background with either its standard input or its standard output connected to a pipe which you can use in a redirection on the main command. Here you want to filter the standard error, so redirect it to an output process substitution, and redirect the output of the filter command back to stderr.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ stuff 2> >(filter >&2)
standard output
more output
standard error

Note that there are two > characters with a space in between: that's 2> to redirect standard output and >(…) to make a process substitution. The space is necessary because 2>>… would be parsed as an append redirection.

None of the usual shells (even zsh) permit pipes with the | operator other than from stdout to stdin. But all Bourne-style shells support file descriptor reassignment (as in 1>&2). So you can temporarily divert stdout to fd 3 and stderr to stdout, and later put fd 3 back onto stdout. If stuff produces some output on stdout and some output on stderr, and you want to apply filter on the error output leaving the standard output untouched, you can use { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1
standard output
more output
standard error

Ksh, bash and zsh support pipes on arbitrary file descriptors, but they work differently: one command is the main command, and you can pipe its input or output into another command. Process substitution runs a command in the background with either its standard input or its standard output connected to a pipe which you can use in a redirection on the main command. Here you want to filter the standard error, so redirect it to an output process substitution.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ stuff 2> >(filter)
standard output
more output
standard error

Note that there are two > characters with a space in between: that's 2> to redirect standard output and >(…) to make a process substitution. The space is necessary because 2>>… would be parsed as an append redirection.


To make this approach function like the first part of the answer, redirect the output of the filter command back to stderr:

    ︙
$ stuff 2> >(filter >&2)
In the second code snippet, the output of the filter function should also be redirected to STDERR, otherwise it is written to STDOUT.
Source Link

None of the usual shells (even zsh) permit pipes with the | operator other than from stdout to stdin. But all Bourne-style shells support file descriptor reassignment (as in 1>&2). So you can temporarily divert stdout to fd 3 and stderr to stdout, and later put fd 3 back onto stdout. If stuff produces some output on stdout and some output on stderr, and you want to apply filter on the error output leaving the standard output untouched, you can use { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1
standard output
more output
standard error

Ksh, bash and zsh support pipes on arbitrary file descriptors, but they work differently: one command is the main command, and you can pipe its input or output into another command. Process substitution runs a command in the background with either its standard input or its standard output connected to a pipe which you can use in a redirection on the main command. Here you want to filter the standard error, so redirect it to an output process substitution, and redirect the output of the filter command back to stderr.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ stuff 2> >(filter >&2)
standard output
more output
standard error

Note that there are two > characters with a space in between: that's 2> to redirect standard output and >(…) to make a process substitution. The space is necessary because 2>>… would be parsed as an append redirection.

None of the usual shells (even zsh) permit pipes with the | operator other than from stdout to stdin. But all Bourne-style shells support file descriptor reassignment (as in 1>&2). So you can temporarily divert stdout to fd 3 and stderr to stdout, and later put fd 3 back onto stdout. If stuff produces some output on stdout and some output on stderr, and you want to apply filter on the error output leaving the standard output untouched, you can use { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1
standard output
more output
standard error

Ksh, bash and zsh support pipes on arbitrary file descriptors, but they work differently: one command is the main command, and you can pipe its input or output into another command. Process substitution runs a command in the background with either its standard input or its standard output connected to a pipe which you can use in a redirection on the main command. Here you want to filter the standard error, so redirect it to an output process substitution.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ stuff 2> >(filter)
standard output
more output
standard error

Note that there are two > characters with a space in between: that's 2> to redirect standard output and >(…) to make a process substitution. The space is necessary because 2>>… would be parsed as an append redirection.

None of the usual shells (even zsh) permit pipes with the | operator other than from stdout to stdin. But all Bourne-style shells support file descriptor reassignment (as in 1>&2). So you can temporarily divert stdout to fd 3 and stderr to stdout, and later put fd 3 back onto stdout. If stuff produces some output on stdout and some output on stderr, and you want to apply filter on the error output leaving the standard output untouched, you can use { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1
standard output
more output
standard error

Ksh, bash and zsh support pipes on arbitrary file descriptors, but they work differently: one command is the main command, and you can pipe its input or output into another command. Process substitution runs a command in the background with either its standard input or its standard output connected to a pipe which you can use in a redirection on the main command. Here you want to filter the standard error, so redirect it to an output process substitution, and redirect the output of the filter command back to stderr.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ stuff 2> >(filter >&2)
standard output
more output
standard error

Note that there are two > characters with a space in between: that's 2> to redirect standard output and >(…) to make a process substitution. The space is necessary because 2>>… would be parsed as an append redirection.

correct statement about pipes (it was only correct for pipelines, process substitutions are a different kind of pipe)
Source Link
Gilles 'SO- stop being evil'
  • 857.8k
  • 202
  • 1.8k
  • 2.3k

None of the usual shells (even zsh) permitspermit pipes with the | operator other than from stdout to stdin. But all Bourne-style shells support file descriptor reassignment (as in 1>&2). So you can temporarily divert stdout to fd 3 and stderr to stdout, and later put fd 3 back onto stdout. If stuff produces some output on stdout and some output on stderr, and you want to apply filter on the error output leaving the standard output untouched, you can use { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1
standard output
more output
standard error

Ksh, bash and zsh support pipes on arbitrary file descriptors, but they work differently: one command is the main command, and you can pipe its input or output into another command. Process substitution runs a command in the background with either its standard input or its standard output connected to a pipe which you can use in a redirection on the main command. Here you want to filter the standard error, so redirect it to an output process substitution.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ stuff 2> >(filter)
standard output
more output
standard error

Note that there are two > characters with a space in between: that's 2> to redirect standard output and >(…) to make a process substitution. The space is necessary because 2>>… would be parsed as an append redirection.

None of the usual shells (even zsh) permits pipes other than from stdout to stdin. But all Bourne-style shells support file descriptor reassignment (as in 1>&2). So you can temporarily divert stdout to fd 3 and stderr to stdout, and later put fd 3 back onto stdout. If stuff produces some output on stdout and some output on stderr, and you want to apply filter on the error output leaving the standard output untouched, you can use { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1
standard output
more output
standard error

None of the usual shells (even zsh) permit pipes with the | operator other than from stdout to stdin. But all Bourne-style shells support file descriptor reassignment (as in 1>&2). So you can temporarily divert stdout to fd 3 and stderr to stdout, and later put fd 3 back onto stdout. If stuff produces some output on stdout and some output on stderr, and you want to apply filter on the error output leaving the standard output untouched, you can use { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ { stuff 2>&1 1>&3 | filter 1>&2; } 3>&1
standard output
more output
standard error

Ksh, bash and zsh support pipes on arbitrary file descriptors, but they work differently: one command is the main command, and you can pipe its input or output into another command. Process substitution runs a command in the background with either its standard input or its standard output connected to a pipe which you can use in a redirection on the main command. Here you want to filter the standard error, so redirect it to an output process substitution.

$ stuff () {
  echo standard output
  echo more output
  echo standard error 1>&2
  echo more error 1>&2
}
$ filter () {
  grep a
}
$ stuff 2> >(filter)
standard output
more output
standard error

Note that there are two > characters with a space in between: that's 2> to redirect standard output and >(…) to make a process substitution. The space is necessary because 2>>… would be parsed as an append redirection.

Source Link
Gilles 'SO- stop being evil'
  • 857.8k
  • 202
  • 1.8k
  • 2.3k
Loading