5 ms·
It always confused me when tools don't follow that rule. Eg: "find" where "find . --name '.dat'" won't work but "find . -name '.dat'" will and it's not the only
by mickael-kerjean 6y ago
It always confused me when tools don't follow that rule. Eg: "find" where
"find . --name '.dat'" won't work but "find . -name '.dat'" will and it's not the only one
- ainar-g 6y agoLegacy and backwards-compatibility. find(1) is a really funny example, too, because POSIX find doesn't have that many flags, so they could probably fit all of them into the short format.
- ben0x539 6y ago`find` is weird anyway. The stuff after the arguments aren't really flags, they're a tiny filter language, with significant ordering and operator precedence and all that stuff. Using "normal" option syntax wouldn't make a lot of sense for it either.
- chubot 6y agoYes exactly, find is like test a.k.a [. 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/ 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.
- chubot 6y agoRelated: Problems With the test Builtin: What Does -a Mean? http://www.oilshell.org/blog/2017/08/31.html http://www.oilshell.org/blog/2017/08/31.html
- ainar-g 6y agoThanks for the article! How did I not see this before? Didn't know that POSIX has obsoleted -a and -o either. I guess I have some shell scripts to rewrite, heh.
- ben0x539 6y agoI feel like `jq` does the "more like a language" thing better than `find`, but possibly its just a product of its time.
- chubot 6y agoWell the thing find and test have in common is that they lack a lexer! They abuse the argv array for tokens instead. I might call it the "I'm too lazy to write a lexer" pattern :) 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: https://stedolan.github.io/jq/manual/ https://stedolan.github.io/jq/manual/
- grishka 6y agoFind 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.
- throwawayboise 6y agoI 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.
- grishka 6y agoYes, 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?
- wahern 6y agoIt'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/find/main.c#L89 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/ftsfind.c#n596 https://git.savannah.gnu.org/cgit/findutils.git/tree/find/ft... Hint, see https://git.savannah.gnu.org/cgit/findutils.git/tree/find/util.c#n926 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.
- thitcanh 6y agoIf anyone is looking for alternatives, try fd https://github.com/sharkdp/fd https://github.com/sharkdp/fd
- beltsazar 6y agofd is even more than that. In most cases `fd -x` can replace `find ... | xargs ...`.
- Hnrobert42 6y agoFrom the article, it sounds like find predates the two dashes convention, so I think it gets a pass.
- m463 6y agoalso: tar xvf foo.tar