Fd: Thoughts on non-zero exit code for no matches?

Created on 11 Jun 2018  ·  12Comments  ·  Source: sharkdp/fd

grep returns a non-zero exit code when no matches are found, making it easy to include in shell scripts and if conditions directly without having to shell out to test to analyze the results.

What are your thoughts on having fd do the same so that fd not-exists and fd exists have differing exit codes that could be directly checked?

feature-request

Most helpful comment

Ok, let's try to implement this. I like --test. We can probably reuse the --max-results functionality and run a --max-results=1 search. Instead of printing anything to the console, we would simply return 0 or 1, depending on whether we have at least one result or not.

if fd --test pattern; then
  ...
fi

What do you think @ChrisPenner @mqudsi @vn971?

In particular, the decision not to print anything? Otherwise, we would have to use > /dev/null in scripts. And we already have fd -1 pattern to print the first search result and quit.

All 12 comments

Thank you for the feedback!

Interesting thought. However, I'm not sure that it's a good idea to implement it this way. find always returns 0 if it finished the search without any errors, even if there are no results.

The idea is that you can use the exit code to tell whether or not you can rely on the search results. If the exit code is non-zero, there might be folders/files which were not searched (due to permission issues, for example). I believe we should probably do the same with fd (we currently silently ignore these).

Coming back to your use case, I agree that it would be nice to use fd this way in shell scripts, but I guess there are some rather simple workarounds that would achieve the same, for example

fd ... |  grep .

Fair enough.

It does occur to me that a better option here (if one were to want to improve this) might be to add a --has-results or similar flag that _would_ use the 0/1 return code, which has the added benefit of allowing fd to terminate early when a match is found.

If you want early return, you can use head -n 1:

fd ... | head -n 1 | grep .

I'm going to close this as there are reasonable solutions including other CLI tools.

Good reasoning for not giving exit code by default in the second comment, thanks for explaining.

To enumerate the benefits of a built-in CLI option, however:

  • we can list the flag in --help and the man page, which can lead to people getting their job done faster. After all, it is a common requirement to test for emptiness.
  • there's a tiny overhead in calling 2 extra binaries piped together, even though that's more aesthetics than practical concern (for most people?)
  • it's more readable: fd --quiet something VS fd something | head -c 1 | grep . 1>/dev/null
  • not everybody is a pro at bash (who is, anyway?), it's nice when you can get the job done faster and simpler

In the meantime (since writing the comments above) there have been some new developments:

We now have a --max-results=<count> option and a -1 alias for --max-results=1 that can be used to exit early after finding the first result(s). This is even faster than the early exit via fd … | head -n1 because the latter is actually running until the second result.

we can list the flag in --help and the man page, which can lead to people getting their job done faster. After all, it is a common requirement to test for emptiness.

Ok, agreed. But I would assume that this use case (testing for existence of search results) is something that usually comes up in a script, not in the interactive use of a terminal. Therefore, I don't think it's too bad if there is no super-short way to achieve that result is found.

there's a tiny overhead in calling 2 extra binaries piped together, even though that's more aesthetics than practical concern (for most people?)

As you said, I think that's negligible compared to the IO overhead (accessing the disk / cache) to get the search results.

  • it's more readable: fd --quiet something VS fd something | head -c 1 | grep . 1>/dev/null

Fair point. I think there are slightly more readable alternatives though:

if [[ $(fd -1 …) ]]; then
  echo "found something!"
else
  echo "did not find anything"
fi
  • not everybody is a pro at bash (who is, anyway?), it's nice when you can get the job done faster and simpler

Ok. Let's reopen this ticket and see what others think.

Just chiming in that I'd also appreciate a flag for setting exit status :)

Sure, the given alternatives work; but I'd need to add a comment to have any faith that anyone would understand why. If I saw something like fd something | head -c 1 | grep . 1>/dev/null I'd have no clue what the intent was; whereas if I saw:

if fd --set-exit-status 'pattern'; then
  ...
fi

Then the intent is clear and my coworkers won't get confused 😄

Alternative names for the option could be --test or --match

Ok, let's try to implement this. I like --test. We can probably reuse the --max-results functionality and run a --max-results=1 search. Instead of printing anything to the console, we would simply return 0 or 1, depending on whether we have at least one result or not.

if fd --test pattern; then
  ...
fi

What do you think @ChrisPenner @mqudsi @vn971?

In particular, the decision not to print anything? Otherwise, we would have to use > /dev/null in scripts. And we already have fd -1 pattern to print the first search result and quit.

I guess the decision to not print anything makes even more sense if the flag is called --silent / --quiet. Another argument in favor of that naming would be that it's standard in CLI tools (grep, curl, wget, indirectly ssh, indirectly ping, etc)

@sharkdp I love it. --test sounds good to me and reminds me of the test command, which is good since this is similar to how that command is used. I also like the idea of hiding output. It makes it faster if we only need to find a single match, and if we WERE printing something it'd be very unintuitive to only print a single thing. Hiding it all seems best to me 👍

I believe that -q/--quiet is "the norm" for this sort of behavior (no output + early termination if possible), --test doesn't really imply anything that one could intuit as being suppression of output.

I still feel that in addition to/apart from any "fast eval" mode, the standard exit code should also reflect the match/no match status to match standard unix tools like grep and find.

I believe that -q/--quiet is "the norm" for this sort of behavior (no output + early termination if possible),

Really? I would expect a --quiet option to do exactly the same, but without the output. The option that is being proposed here would change the behavior (only search for the first result, then quit).

--test doesn't really imply anything that one could intuit as being suppression of output.

that's true, but it would be used to test if a search has a match. Another possibility would be --check or --has-match ….

I still feel that in addition to/apart from any "fast eval" mode, the standard exit code should also reflect the match/no match status to match standard unix tools like grep and find.

I argued above that we don't want to do this because it would not reflect what find does. find does return 0 if there are no matches (and no filesystem errors have occurred). We don't necessarily have to be consistent with find, but in this case, I think we should aim to be.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ChengCat picture ChengCat  ·  3Comments

matu3ba picture matu3ba  ·  4Comments

mathomp4 picture mathomp4  ·  4Comments

kclevenger picture kclevenger  ·  3Comments

runiq picture runiq  ·  3Comments