2

I am the author of a find replacement which attempts to be compatible with POSIX (and with many popular extensions). Recently I noticed a discrepancy between the behaviour of my utility and other find implementations, and I want to know if POSIX allows my behaviour or if I need to change it.

$ find . -exec /no/such/file {} \;
find: ‘/no/such/file’: No such file or directory
$ echo $?
0
$ bfs . -exec /no/such/file {} \;
bfs: error: .: -exec /no/such/file: No such file or directory.
$ echo $?
1

At least GNU, busybox, and FreeBSD find all have exit status 0 in this case. My implementation propagates the execv() error from the fork()ed child to the parent, while the other implementations seem to print the error directly from the child without telling the parent.

The reason I ask this question, rather than just change the behaviour to match the others, is that it seems difficult to do when using posix_spawn(). Implementations of posix_spawn() are allowed to propagate execv() errors to errno in the parent, and e.g. glibc and musl both do this. It seems impossible to tell whether the error occurred before or after the fork(), and presumably errors from before the fork() (e.g. ENOMEM) should lead to a non-zero exit status.

I have read the POSIX specification for find, but it's light on details here. However, I've heard that there are other rules documented elsewhere that might be relevant. For example, I've heard that if a utility prints to standard error, it must also exit with a nonzero exit code, which seems to imply that the other finds are not compliant. But I'm not sure where that wording is, or if it really exists.

8
  • 1
    There is no rule about having to exit with a non-zero exit code just because something was outputted to standard error. If there was, no standard shell would ever exit interactive mode with a zero exit code (the PS1 prompt is written to standard error).
    – Kusalananda
    May 31, 2022 at 16:55
  • @Kusalananda The context I saw this in was about GNU find's handling of -warn/-nowarn and POSIXLY_CORRECT. GNU find defaults to -nowarn if POSIXLY_CORRECT is set, due to a concern about whether they're allowed to print the warnings and exit successfully. I'll try to dig up a link to the discussion. May 31, 2022 at 17:00
  • So this is specifically about what the correct behaviour is for a non-standard find implementation depending on the use of non-standard predicates and the values of some non-standard environment variable?
    – Kusalananda
    May 31, 2022 at 17:03
  • Ah, here it is: savannah.gnu.org/bugs/?21039. I'm trying to find a non-dead copy of the opengroup link. May 31, 2022 at 17:03
  • @Kusalananda No, I'm just explaining the context where I heard that. The question itself is about POSIX-compliant functionality. May 31, 2022 at 17:04

1 Answer 1

2

The POSIX specification for find says, in its STDERR section,

Otherwise, the standard error shall be used only for diagnostic messages.

(“Otherwise” follows a description of -ok, which isn’t relevant here.)

This needs to be understood in light of the Utility Description Defaults, which specify that

When this section is listed as "The standard error shall be used only for diagnostic messages.", it means that, unless otherwise stated, the diagnostic messages shall be sent to the standard error only when the exit status indicates that an error occurred and the utility is used as described by this volume of POSIX.1-2017.

So it’s not true that all POSIX compliant utilities are only allowed to output to standard error if they exit with a status indicating an error; but it is true for utilities with the specific mention, and that includes find.

6
  • Thanks for finding this wording! I've been looking for it for a while. I guess the remaining question is now, "should find . -exec /no/such/file {} \; be printing those messages at all?" May 31, 2022 at 18:10
  • 1
    You're saying, and I think I agree that POSIX currently requires find to exit with a non-zero exit status if it fails to execute the utility and outputs an error message about it. I've not seen any find implementation that would be compliant in that regard, so it could be seen as a defect in the specification. It may be worth bringing it up to the Austin Group. The spec is also not clear to me how the utility is looked up and executed. It seems to me it should say something like "as if using execvp()...". Only the environment section hints at a $PATH lookup May 31, 2022 at 18:10
  • ... I suppose find implementations could have some utilities builtin like busybox find is able to skip the fork+exec. May 31, 2022 at 18:14
  • @StéphaneChazelas I’ll open an issue (probably not before this weekend). May 31, 2022 at 18:38
  • May be worth asking informally on the austin-group-l mailing list first as we could very well be missing something obvious. May 31, 2022 at 19:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .