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