On every POSIX shell I can test[*] except bash, ksh93 and FreeBSD sh, it
is possible to capture a command's output to standard error in a
variable like so:

$ ls_err=$(set +x; ls -l /dev/null/nonexistent /bin/sh 2>&1 1>&3) 3>&1
/bin/sh
$ echo "$ls_err"
ls: /dev/null/nonexistent: Not a directory

On bash and FreeBSD sh, this results in an error:

$ ls_err=$(set +x; ls -l /dev/null/nonexistent /bin/sh 2>&1 1>&3) 3>&1
$ echo "$ls_err"
-bash: 3: Bad file descriptor

On ksh93, standard output is discarded but not standard error:

$ ls_err=$(set +x; ls -l /dev/null/nonexistent /bin/sh 2>&1 1>&3) 3>&1
$ echo "$ls_err"
ls: /dev/null/nonexistent: Not a directory

It does work on both bash, ksh93 and FreeBSD sh when you use curly
braces as a workaround:

$ { ls_err=$(set +x; ls -l /dev/null/nonexistent /bin/sh 2>&1 1>&3); } 3>&1
/bin/sh
$ echo "$ls_err"
ls: /dev/null/nonexistent: Not a directory

Should the necessity of these curly braces be considered a bug?

- M.

[*] Confirmed to work without the curly braces on dash, Busybox ash,
yash, pdksh, mksh/lksh, and zsh

Reply via email to