test -f foo -a -f bar -o -z foo
can be read isfile('foo') && isfile('bar') || emptystring('foo')
Likewise find . -name '*.py' -a -executable -o -printf '%P\n'
can be read (F.name matches '*.py') && (F is executable) || print('%P\n', F)
where F is the current node in the file system traversal.They both respect -o as OR, ! as NOT, and ( ) for precedence, which you have to quote as \( and \).
A couple years ago, someone helped me implement a better "find" without this wonky syntax for https://www.oilshell.org/ . But it isn't done and needs some love. If anyone wants to help, feel free to join Zulip :)
I do think that "find" is more like a language than a command line tool. It's pretty powerful, e.g. I just used it to sort through 20 years of haphazard personal backups.
jq has a lexer and hence a "real" syntax, but so does awk, which is maybe 30 years older. But yes jq is a surprisingly big and rich language, maybe bigger than awk:
$ 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?
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.
It's not like the source code is now etched into stone and can't be changed. Or is it?
Several BSD commands are pickier than GNU commands about option order, sometimes for good reason, sometimes because it was easier to write that way.
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.
tar xvf foo.tar