23 ms·
Here's how zsh 5.8 behaves on macOS: $ which {which,type,command,vi} which: shell built-in command type: shell built-in command command: shell
by jagger27 5y ago
Here's how zsh 5.8 behaves on macOS:
$ which {which,type,command,vi}
which: shell built-in command
type: shell built-in command
command: shell built-in command
/usr/bin/vi
$ type {which,type,command,vi}
which is a shell builtin
type is a shell builtin
command is a shell builtin
vi is /usr/bin/vi
$ command -v {which,type,command,vi}
which
type
command
/usr/bin/vi
Which is quite different from how bash 5.1 behaves:
bash-5.1$ which {which,type,command,vi}
/usr/bin/which
/usr/bin/type
/usr/bin/command
/usr/bin/vi
bash-5.1$ type {which,type,command,vi}
which is hashed (/usr/bin/which)
type is a shell builtin
command is a shell builtin
vi is /usr/bin/vi
bash-5.1$ command -v {which,type,command,vi}
/usr/bin/which
type
command
/usr/bin/vi
I wouldn't want to be the one responsible for making this change, that's for sure.
command -v does seem like the most reasonable choice in both circumstances, though.
/usr/bin/type and /usr/bin/command are indeed just the same shell scripts.
file /usr/bin/{which,type,command}
/usr/bin/which: Mach-O universal binary [...]
/usr/bin/type: POSIX shell script text executable, ASCII text
/usr/bin/command: POSIX shell script text executable, ASCII text
cat /usr/bin/command
#!/bin/sh
# $FreeBSD: src/usr.bin/alias/generic.sh,v 1.2 2005/10/24 22:32:19 cperciva Exp $
# This file is in the public domain.
builtin `echo ${0##*/} | tr \[:upper:] \[:lower:]` ${1+"$@"}
- anonydsfsfs 5y ago"command -v" isn't reliable because several shells (including Dash) don't obey the POSIX standard. See https://github.com/oilshell/oil/blob/8fbc09bb3254cee944b0450f640e268c2f627bec/spec/builtins2.test.sh#L78 https://github.com/oilshell/oil/blob/8fbc09bb3254cee944b0450...
- lucb1e 5y agoI checked your link but I don't quite get it. Is status=0 supposed to be a check rather than an assignment? Either way, it doesn't have that behavior like that for me on Debian: it behaves the same as bash. This is in dash: $ command -v whoami /usr/bin/whoami $ echo $? 0 $ command -v echo echo $ echo $? 0 $ command -v nonexistent $ echo $? 127 So that is with both a proper command (whoami), a shell built-in (echo), and neither (nonexistent). It's all as I would expect from a shell. Bash does exactly the same, although dash chooses 127 as exit status and bash chooses 1 but they're both nonzero (thus error statuses).
- detuur 5y agoThen that's too bad for anyone who tries to use non-standard shells. It's one thing to violate a vague, rarely used standard. It's quite another to violate what is most likely the most broadly supported standard on *nix systems.
- anonydsfsfs 5y agoDash is Debian's default non-interactive shell, and it isn't POSIX compliant. The only way to get POSIX compliance on Debian is to switch to a different shell (e.g. bash).
- pxc 5y agoWait what macOS has an executable called `command`? Does any other OS?
- jagger27 5y agoIt’s a shell built-in.
- pxc 5y agoNo, macOS has an executable called `command` so that it is available even on shells that don't implement the builtin
- jagger27 5y agoIf you look at the last part of my comment, you’ll see it’s just a shell script that invokes the built-in.
- pxc 5y agoYeah, I discovered that after I made my previous comment, and before I saw your whole long one. It's a weird choice, because it means that command will sometimes tell you about 'builtins' that are not actually built in to the shell you invoke it from, including `command` itself.
- kayodelycaon 5y agoBSD and Linux do.
- pxc 5y agoWhat Linux distros do? The comments in the `command` script on macOS indicate that FreeBSD included a separate executable for `command` in 2005. But there's no package in all of Nixpkgs providing a `command` executable and the command-not-found handler for Ubuntu doesn't suggest anything either. The norm, afaict, is for `command` to be a shell built-in only, and not available as a separate program.
- deleted 5y ago[deleted]
- zvr 5y agoAs was pointed in many other places, you should also check the output when an alias is used.
- arp242 5y agoPlus shells also behave different depending on how it's invoked (e.g. as "sh" rather than "zsh" or "bash") which can affect the output of these builtins. My own preference these days is to explicitly use /bin/zsh and just rely on zsh behaviour (e.g. "$+commands[ls]"). It's not "compatible" in the sense of "POSIX compatible", but it's more compatible in the sense of "much higher chance everything will work on a random system", with the only downside that people will need to install zsh. I think that's a fair trade-off for many (though obviously not all) cases.