Skip to content

SC3021 warning is bogus #2520

Closed
Closed
@bhaible

Description

@bhaible

For bugs

  • Rule Id (if any, e.g. SC1000): SC3021
  • My shellcheck version (shellcheck --version or 'online'): online
  • I tried on shellcheck.net and verified that this is still a problem on the latest commit
  • It's not reproducible on shellcheck.net, but I think that's because it's an OS, configuration or encoding issue

Here's a snippet or screenshot that shows the problem:

#!/bin/sh
func ()
{
  ofd=3
  {
    echo hi
  } >& $ofd
}
func 3>&1

Here's what shellcheck currently says:

Line 7	SC3021: In POSIX sh, >& is undefined.

Here's what I wanted or expected to see:

Expected output: No warning.

Rationale:

  1. This is perfectly well defined in POSIX. The newest POSIX release is at https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/ . There, the description of sh is at https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/sh.html , and the description of the shell language is at https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/V3_chap02.html . Here, section 2.7 describes redirections, and section 2.7.6 describes the >& operator.

The description says "If word evaluates to one or more digits, the file descriptor denoted by n, or standard input if n is not specified, shall be made to be a copy of the file descriptor denoted by word".

$ofd is a valid word in this place, because: When you look at the grammar in section 2.10.2, the token >&, represented by GREATAND is followed by filename, and filename has the comment "Apply rule 2", and rule 2 says "The expansions specified in [Redirection] shall occur."

  1. The wiki page https://www.shellcheck.net/wiki/SC3021 refers to https://www.shellcheck.net/wiki/SC3020, which cites as the reason "&> is a bash and ksh extension for redirecting both stdout and stderr." But that does not apply to >&. This test (with bash 5.0.17) proves that >& does not redirect stderr:
$ bash -c '{ { echo hi 1>&2; } >& 3 ; } 3>&1' 
hi
$ bash -c '{ { echo hi 1>&2; } >& 3 ; } 3>&1 2>/dev/null' 
  1. The program foo.sh
#!/bin/sh
func ()
{
  ofd=3
  {
    echo hi
  } >&$ofd
}
func 3>&1

prints 'hi', with no error or warning. Tested with

  • bash 5.0.17
  • FreeBSD 13.0 sh
  • NetBSD 9.2 sh
  • OpenBSD 7.0 sh
  • macOS 10.13 sh
  • AIX 7.1 sh
  • Solaris 10 /usr/bin/sh, /usr/5bin/sh, /usr/xpg4/bin/sh
  • Solaris 11.3 sh
  • dash 0.5.10.2
  • BusyBox sh

In other words, there is no actual portability problem with this code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions