6 ms·
'command -v' is POSIX!! I have always avoided it in favor of which because its output doesn't feel machine friendly.
by dilawar 5y ago
'command -v' is POSIX!! I have always avoided it in favor of which because its output doesn't feel machine friendly.
- Taywee 5y agoWhat's not machine-friendly about `command -v`'s output? Can you not just use the exit status? Or did you mean that you avoid `which` in favor of `command -v`?
- guerrilla 5y agoSee my post above.
- goohle 5y ago$ which true /usr/bin/true $ command -v true true $ which ls /usr/bin/ls $ command -v ls alias ls='ls --color=auto'
- Taywee 5y agoIn this case, `which` is just searching the `PATH` and not telling you what will actually run. `command` is correctly informing you of the whole story. I'll add that `which` on my setup is using the zsh built-in, which also informs of aliases and built-ins. So yes, that's more useful if you're using `which` to determine "Does this name exist as an executable anywhere in the PATH", but most people use it to mean "What will actually be executed if I run this word as a command?" edit: Or, most often in scripts, it's used just for its exit status to tell whether the command exists to be executed at all.
- marcosdumay 5y ago> `command` is correctly informing you of the whole story. You are assuming a bit too much here. Which tells you the preferred executable with that name, while command tells you what will run if you execute it on the current shell. From what I can tell, one does not replace the other. But yes, for your example of usage, command is more correct.
- deleted 5y ago[deleted]
- anderskaseorg 5y agoIn a script, there will almost never be any aliases defined, because noninteractive shells don’t load ~/.bashrc. $ sh -c "which ls; command -v ls" /bin/ls /bin/ls If the script is #!bash rather than #!sh, it’s not even possible to define an alias. $ bash -c "alias ls='ls --color=auto'; which ls; command -v ls" /bin/ls /bin/ls
- pxc 5y agoYou can still define functions in scripts, and those might wrap commands or accidentally share their names.
- simias 5y agoI learned about `command -v` just now reading this article. I only knew of `which` and `type` (as well as the very convenient `=executable` syntax that expands to the path of the binary, but I think that's a zsh-ism). What makes `command -v` not machine friendly? It seems to always output just the PATH, unlike type which tries to be human friendly.
- guerrilla 5y agoIt's pretty much useless for the same purpose: $ which ls /usr/bin/ls $ type ls ls is aliased to `ls --color=auto' $ command -v ls alias ls='ls --color=auto' Suddenly I find myself irritated at Debian despite not even using it. Why would they not just include the GNU one?
- jwmhjwmh 5y agoI think aliases are only used in interactive shells: $ sh -c 'command -v ls' /bin/ls
- scbrg 5y agoThis is a very unlikely output when run from a script using the /bin/sh interpreter on Debian, though. If that is the output you've gone out of your way to create an alias in a script, in which case it's reasonable output. It is what will happen when the script runs that command, after all.
- guerrilla 5y agoI'm certain there's masses of code that depends on `which` responding the way it does and scripts with aliases in them regardless of whether that was the right way to do it or not, so your point is probably irrelevant in the grand scheme of things. Think about all that enterprise install and setup crap. People still depend on that spaghetti trash working.
- Taywee 5y agoThat depends on whether your shell has a built-in which or not. Mine says % which ls ls: aliased to /bin/ls --color=auto Which makes way more sense. Your "which" is not telling you what will actually be executed when you run the `ls` command there. `command`, on the other hand, is guaranteed to be a built-in, has consistent behavior, and has defined, consistent output, unlike `which`. What `which` outputs will be different depending on shell and what implementation of `which` you actually have installed.
- mshockwave 5y agoI noticed that on Ubuntu at least, `command -v` has the same output format of `which`, where `command -V` does not. Did you accidentally use the latter one?
- deleted 5y ago[deleted]
- nonameiguess 5y agoshellcheck throws a lint error if it finds you using which and tells you to use 'command -v' instead.
- hdjjhhvvhga 5y agoThank you for reminding me about this neat tool, it saved my ass a couple of times.
- sigzero 5y agoI just tried it on the shellcheck site. It didn't flag it.
- Enginerrrd 5y agoWhat a mess. It sounds like command -v should have been the default from the get go and which should never have been introduced to debianutils. Once it was though, IMO, debian should never make a decision that breaks existing functionality. In general, I don't care if you extend features beyond POSIX in your core utilities, but once you do, you have to assume people rely on that functionality. I think this is the most poignant take: >A proper transition plan would mean that I would never even notice this. One which would replace another and nothing would break. That is the sort of thing I expect to happen in Debian - we are generally good at this stuff, and it's a big reason for using the distro.
- chasil 5y agoI am fairly certain that which came first. This is the POSIX specification for command: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/command.html https://pubs.opengroup.org/onlinepubs/9699919799/utilities/c...
- Taywee 5y agoNotable sections from that page: > The command -v and -V options were added to satisfy requirements from users that are currently accomplished by three different historical utilities: type in the System V shell, whence in the KornShell, and which in the C shell. Since there is no historical agreement on how and what to accomplish here, the POSIX command utility was enhanced and the historical utilities were left unmodified. The C shell which merely conducts a path search. The KornShell whence is more elaborate-in addition to the categories required by POSIX, it also reports on tracked aliases, exported aliases, and undefined functions. > The output format of -V was left mostly unspecified because human users are its only audience. Applications should not be written to care about this information; they can use the output of -v to differentiate between various types of commands, but the additional information that may be emitted by the more verbose -V is not needed and should not be arbitrarily constrained in its verbosity or localization for application parsing reasons.
- denton-scratch 5y ago
- anonydsfsfs 5y ago"command -v" in Dash (the Debian shell) has a serious bug that makes it non-POSIX compliant: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264
- lucb1e 5y agoTo be honest it's kind of weird to have things in your PATH that are not meant to be executed, so I'm not sure I agree about it being that important and it doesn't seem to have gotten any attention since 2017 despite a patch being available, but I take your point that this should not happen and is of course noncompliant.
- wahern 5y agoIf you're parsing the output of `command -v`, you're doing it wrong: if command -v foo >/dev/null; then foo ... else bar fi From shell scripts it doesn't matter if foo is an alias because if it is an alias, it's one that the script created itself. For interactive use, just go ahead and use which if that's what you like. Most people will be using bash or z-shell or whatever, and portability isn't a concern. Interactive shell usage and shell scripting are quite distinct. Yes, there's a huge overlap, but as in any other language, when you're writing a properly structured program (not a one-off or hack), you're expected (for good reasons) to follow more consistent rules and conventions.
- pmontra 5y agoI'm not sure I knew about type. I didn't know about command -v probably because I learned which close to 35 years ago and I didn't have to look for a different way to do it.