Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Find is about as user-unfriendly as a shell command could be. I never get it to do what I want on the first try. And its error messages are always cryptic and unhelpful.


I don't think any shell commands are particularly "friendly." Most are intentionally terse (in fact I find verbose, "friendly" command options to be annoying), and you learn them by repeated use, or for those that you use only occasinally, by consulting the man pages.


Yes, but errors are at least somewhat helpful. With find, it's this:

    $ find -name something
    find: illegal option -- n
    usage: find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]
           find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]
What does "illegal option" mean exactly? Why is it "n" which is the first letter of "-name"? Yes, it wants a path. Yes, even if you want to search in the current directory. Yes, it IS unusual, because all other commands that operate on directories, like `ls`, assume current directory if you don't specify any.

Why could it not just say "a path is required" instead?


It's saying that because it's using getopt to parse any initial option arguments. That diagnostic message is the standard default message printed by the getopt function whenever encountering an invalid option flag. It means all utilities using getopt will, unless you disable the default behavior, display the same initial diagnostic. It's idiomatic for utilities to then print a short usage message of its own.

Judging by the usage message you printed, you were almost certainly using a BSD implementation, probably on macOS, which in turn is probably sync'd from FreeBSD. `find -name something` will fail early in main. See https://github.com/freebsd/freebsd-src/blob/b422540/usr.bin/... When processing the 'n' in '-name' getopt() will return '?', which will end up calling usage().

The GNU implementation of find is completely different, though I'm not sure it does what you expect:

  $ find -name something
That prints nothing and returns a successful exit code. But if you remove the "something" operand you get what I presume you were originally expecting as an error message:

  $ find -name
  find: missing argument to `-name'
But try deciphering the option processing of GNU find to understand why it behaves that way: https://git.savannah.gnu.org/cgit/findutils.git/tree/find/ft... Hint, see https://git.savannah.gnu.org/cgit/findutils.git/tree/find/ut...

Not rocket science, but as a programmer and maintainer which approach do you think makes more sense? Is trying to do the supposedly intuitive thing worth it, especially considering find's already arcane and irregular syntax? As an experienced command-line user I'd just be thankful that the option flags (as opposed to the filter directives) are parsed regularly.


This is a good explaination why it has the current behaviour, but it doesn't answer the question of why the behaviour isn't better (i.e. which would be to tell the user what's needed, the path, instead of telling the user what was provided is not what's needed which is vague and leaves it up to the user to figure it out.)

It's not like the source code is now etched into stone and can't be changed. Or is it?


GNU find, or at least my version of GNU find (4.8.0), will just assume "." if the path is missing, and will work as expected. I think various forms of BSD find are a bit more strict, and based on that usage message is seems to be BSD find.


It gave you the list of options (i think that's at most one of -H and friends, as many as you like of -E and friends, -f with an argument), and -n isn't one of them.

Several BSD commands are pickier than GNU commands about option order, sometimes for good reason, sometimes because it was easier to write that way.


This is why I've ultimately come to the conclusion that shells are for casual use only, not for any kind of serious work. There are too many implementation details, inconsistencies, and footguns to write anything that needs to be somewhat reliable.


What do you use instead?


To be fair, there is one shell that I think someday we could rely on. https://www.nushell.sh/ Besides that, my answer is "any programming language," since at the core, dealing properly with system calls and their outputs is the whole reason PL's exist. In practice, I've been using Rust lately which makes a nice systems language, but JS and Python are always options for shell-like scripts that don't suffer from quite the level of degeneracy when encountering weird filenames or unexpected input in general.


> my answer is "any programming language,"

That would be a terrible shell. Changing directories, listing them, moving files, running programs are all simple no-brainer operations in any reasonable shell, but are non-trivial in any programming language that's not designed to be a shell.


So you use the shell for things that require no brain: browsing your directory tree, casual printing of files. Then, when you need to encode these operations in a script, you pull out a scripting language, because you need more than the shell can provide with its casual nature.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: