Skip to content

chgrp/chown --verbose prints "changed/retained" lines to stderr with a util-name prefix instead of stdout #13408

Description

@leeewee

With --verbose, chgrp and chown emit their informational per-file lines (changed ownership of …, ownership of … retained as …, group of … retained as …) to stderr, prefixed with the utility name (chgrp: /chown: ). GNU emits these to stdout with no prefix. They are normal informational output, not errors.

$ tmp=$(mktemp -d); touch "$tmp/f"

# uutils: line goes to stderr, with a "chgrp:" prefix
$ chgrp --verbose "$(id -gn)" "$tmp/f" 1>/dev/null
chgrp: group of '/tmp/…/f' retained as youruser

# GNU: line goes to stdout, no prefix
$ /usr/bin/chgrp --verbose "$(id -gn)" "$tmp/f" 2>/dev/null
group of '/tmp/…/f' retained as youruser

Consequences

  • Redirection is broken. chgrp --verbose grp file > log.txt leaves log.txt empty in uutils (the lines leak to the terminal via stderr); GNU writes them into log.txt.
  • Spurious prefix on informational lines.
  • Exit-code divergence on a failing stdout. Because the lines go to stderr, redirecting stdout to a failing sink doesn't surface a write error:
$ chgrp --verbose "$(id -gn)" "$tmp/f" > /dev/full ; echo "exit=$?"
exit=0        # uutils
# GNU writes to stdout -> ENOSPC -> exit=1

Root cause

The verbose informational lines are produced by report_ownership_change_success in src/uucore/src/lib/features/perms.rs, which uses the show_error! macro. show_error! always writes to stderr and prepends util_name(), so it's the wrong sink for informational output.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions