This feels a little tone-deaf to me. I've been using the *nix command-line and writing (and reading) shell scripts for 20+ years, and I'd never heard of "command -v" until now. Now that I know about it, I'll probably start trying to retrain my muscle memory to use it (though it requires 2x the number of keystrokes).
Despite its lack of true standardization, "which" (along with "type -p") has been the de-facto "standard" I've seen in shell scripts for figuring out if a command exists. It was a surprise to me to learn that "which" isn't a part of POSIX, even.
It's also worth reading through the POSIX manpages for POSIX sh if you want to be a good shell scripter.
Or you can give the middle finger to POSIX, write shell scripts for bash, or even zsh, and end up with faster, more correct, and more beautiful shell scripts that in practice are just as portable as the ones that mindlessly follow the limited and bizarre POSIX shell spec.
I'll write POSIXly-correct shell scripts when the POSIX people stop pretending it's still 1995.
Man can only have one entry (per section) for a given command, but what if you're using Bash? Or Zsh? How would it know which one to give you? If they're named differently (like a manpage for `bash-command` vs `zsh-command`), how would you know to look those up? (never mind that apropos would give you so-overloaded-to-be-useless results for something as generic as `command`)
Which leaves us in the current situation where `man command` redirects to a generic `builtin` manpage, that doesn't have much info, and certainly nothing specific to Bash or Zsh.
The output and return result differ significantly between BSD, GNU and OSX, so you can't just run $(which python) and get a straightforward response back.
Granted, I didn't know about `command -v` so I'm not sure if it works better in practice.
Given that, having it print out a deprecation warning without considering what that means to all the people that use it is irresponsible. I help manage a few hundred servers. We send root email to a list and actually review it all every day. We make sure to sanitize anything run from cron so that we only get email output on error (STDERR). Given that some of those cron jobs run quite often, this would have been thousands of emails to sift through if we used Debian.
There were many possible solutions, as the maintainer notes. Unfortunately in trying to remove themself from the decision, they forced a non-solution on everyone that is disruptive. I can't think of any way this is a good choice for this particular set of facts (I can see a deprecation warning being warranted for some other things, but this case has little to do factually with those theoretical situations).
Ugh. Now that the UNIX universe has collapsed unto Linux, BSD's and very, very few other *X's, it is less of an issue, but «which», due to it having never been enshrined in standards, has never been safe to use in shell scripts, and an invocation could yield a suprise for the unprepared. At least on Solaris (if I am not mistaken), the «which» output yields *two* lines, of which the first is useless (along the lines of «ohiyo, lookie at what I have found») and with the second being the actual path to the binary. So «which» has never been truly portable and safe to use.
None of that helps this specific situation at all, which seems to have been poorly thought out in that it had the possibility of negatively affect many people, and not just the developers/admins who write scripts, but those that use what other people have written.
It's important to strive for chance for the better, but it's also important to see the world for how it actually is and what happens if that change happens all at once, which can (hopefully temporarily) be worse than what came before.
Virtually every command can fail in some way, and they will all write to stderr (or worse, stdout, but that's not what happened here). How is that unexpected at all? How else would you communicate the change? (For the sake of argument, let's say the change is going to happen regardless, since you're arguing for the irresponsibleness of showing a warning.)
1) Require the output of which in non-interactive environments to conform to the behavior a reasonable shell script author is likely to have assumed the specification was based on observations. In the case of historic 'which' that would be to print the absolute path to an executable without any other arguments, or a specific error message and exit status.
2) Allow __interactive__ shells to deviate from that behavior. E.G. with a warning, with alias information, etc.
Stop looking for problems to solve where there are no problems. It's a waste of others' time, not just your own. Be respectful of others' time.
But a lot of the time I see people write some shell script that's Linux or BSD specific in the first place as "compatible" shell scripts. I don't see how that makes much sense. The only advantage I can see is that dash is a bit faster than bash or zsh, but it's not that much of a difference in real scripts.
Shell scripts can run in a myriad of hosts, from VMs to stripped-down containers. When writing robust production code (not to say that shell scripts are ideal for that purpose), you'll want to minimize moving parts and risk surface, so that you can go home more confident that things will just work regardless of what you throw at it.
But which which do you make standard?
When one says it's non-standard, it normally means that you don't know if the way you are using it will work on other places.
You can't quite be. Standards are norms, so there's no escaping normativity there. And simply describing existing conventions can't solve the problems that standards are introduced to solve, which is when you are faced with multiple, sometimes incompatible ways of doing things.
There's room for a kind of descriptivist reconciliation with updates to standards, though. You can say ‘Future versions of the standard should, as far as possible, directly incorporate contemporaneous usage. Where contemporaneous usage is divergent, they should reflect the virtues of contemporaneous usage in a new standard capable of replacing divergent uses.’
Hell, I still see people being stuck with csh scripting sometimes with no alternative (sucks to be them!)
There is some common software that wants to run on all these platforms. Do you or I need to care about that for our Docker build script or whatnot? No, probably not. But that doesn't mean others don't. There's still very much a valid use-case for POSIX, even though it doesn't apply to everything.
Is that a criticism of the FreeBSD userspace? Because that's where much of Apple's UNIX userspace is derived from, and they're regularly synced with upstream.
A lack of alternatives simply means that not enough standardization is happening, and we need more standards compliance.
Slowly, methodically, and with minimal user impact.
As mentioned at the end of the article, what first appears a waste of time for a small issue could also be seen as a beautiful illustration of the democratic process that makes Debian so stable/widely adopted.
I am confused. Isn't the article about an individual just randomly deciding to deprecate which and the resulting fallout that impacted all of Debians users?
That is how things get done. If you do the work you get to decide.
In the 0.001% that an issue get taken up by the technical committee as being important for the whole project, then after usually a long time they make a decision that in special cases may overrule the maintainer. That happens about once or twice a year? I am unsure how often a decision actually goes against the maintainer, and there is only a few cases a year (https://www.debian.org/devel/tech-ctte).
This naturally doesn't stop anyone from being too active on the mailing lists and arguing over small things, but I would think people are wasting less time there than they do arguing lesser important topics on social media.
Many years ago, I posted that stable was too old. All the Debian users were quick to tell me to run testing, that it wasn't a bad experience in spite of the name. Well, after converting all my machines to Debian, a package that was critical to my work was broken and I was not at all impressed with the handling of the situation, so I moved on. I can definitely see something like the story in the article playing out.
I am not a sysadmin and very far from an expert so my take on this is entirely anecdotal and likely partially wrong.
But ever since I moved to Manjaro (after briefly trying Arch and deciding that I don't want to build my own house brick by brick) I've only had 1-2 problems ever and they were fixed literally the day after with the next system-wide update command. The one and only exception is the last problem I had: namely an OpenSSH upgrade hard-deprecated a few signing algorithms so I was unable to SSH into my servers. And that was solved with half a minute of search on ManjaroForum. Smooth sailing.
For all the BS surrounding the "systemd vs. whatever-else-the-other-thing-was", I found the former made my life as a mid-tier Linux user and home-grown server admin much easier, too.
'everyone' = existing users. New users are generally harmed by redundancy and mess.
As in all things, it is a balancing act.
They could just have kept which has it has been for more than a decade and nothing would have happened. That's the decision that prevailed in the end but the fact that it had to go all the way to the Technical Committee before sanity prevailed says a lot about the utter madness of the Debian development process.
It is actually a bit insane that the committee is forcing a developer to support something against their will in a project based on volunteers. It is basically an artifact of the concept of essential packages and an situation where multiple different versions could cause instability, and so until the program can be moved to a different essential package the best move for the project was to keep things as they were.
It's a voluntary organization, I guess people enjoy this, and the decision was taken in the open. There are worse things in the world right now :-)
Debian is extraordinarily successful, so the time seems well spent. Who here has managed an equally successful project?
[Edit] I didn't mean the systemd thing lacked transparency; I just mean the result wasn't "nice".
Heavily used languages evolve. And you know what? They never evolve healthily when they ban the use of "obsolete" vocabulary. Languages embody history. Even PowerShell!
This language won't benefit from an Académie Française - style iron-fisted rule.
$ 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+"$@"}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).
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.
This is partly because of the autonomy that Debian package maintainers enjoy. I have slightly mixed feelings about that - but only slightly. I'd sooner have maintainer autonomy, and seriously-distributed decision making, than an overlord.
You can't use `command -v` in csh or other shells, only in Bourne style shells (bash, zsh, etc).
/usr/bin/which is a standalone binary. It can be invoked without a shell at all.
Many comments discussing `command` being part of POSIX are I think missing that `command` is only part of POSIX insofar as the Bourne shell is defined by POSIX. It is part of a POSIX `/bin/sh` and is not its own thing.
Keeping /usr/bin/which is the correct decision and it should probably be added to POSIX.
If you're specifying your shebang as #!/bin/sh then you should not assume you have access to functions like type or binaries like which, but you can generally assume you have access to the command built-in.
'type' is actually POSIX though. bash does extend it.
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/t...
I understand Bourne style (POSIX) shells have the vast majority of the market, but the point is breaking other environments. "command -v" is not available everywhere so it is not a viable replacement for /usr/bin/which.
What makes `command -v` not machine friendly? It seems to always output just the PATH, unlike type which tries to be human friendly.
$ 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?Me too and I'm sure we're not the only ones. But look at this quote from the article:
> surely no one competent would choose to have a package depend on `which` when a standard POSIX utility can do a better job
This is an mind-bogglingly misguided attitude. Anyone that has never heard of an obscure POSIX command is incompetent? Or is it that really that most people don't want to spend their time writing awful shell scripts and figuring out exactly what is POSIX and what isn't?
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.
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.
This is the POSIX specification for command:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/c...
While I can understand having this attitude, a whole lot of package build scripts, not just in Debian, but in the upstreams, rely upon which existing and printing out the path of an executable without a deprecation warning. I would expect a Debian maintainer to realize that. Debian does patch the heck out of upstream packages, but they don't provide everything, and all Debian users are not going to want to go to equal effort to patch all of the build files for packages Debian doesn't provide.
Those kinds of attitudes pushed me out of open-source engineering and into closed-source, commercial engineering, purely because it's nice to have a boss who can say "Don't talk to your peers like that; it's counterproductive" with some authority.
Probably not. The programs should (and likely actually do) parse only stdout. The warning is on stderr.
I find the whole thing pointless, I disagree with Adams that only incompetent people would depend on which, and I expect actually removing /usr/bin/which to be problematic, but I don't expect the warning itself to break much of anything, except maybe blood pressure cuffs...
As of today all my (scripts') use of which is going to include '2>&1' or the contextually appropriate equivalent. Fuck Clint Adams.
I cannot believe people are parsing text output from other commands in the year 2021. To me that this sounds like incredibly unsafe practice and am just astounded it happens.
If you're writing shell scripts, there aren't any other options.
Here's a lovely little snippet to find the current wifi network for a reMarkable 2. If it's "Aardvark", it runs rsync. :)
iw wlan0 info | grep -Po '(?<=ssid ).*' | tr -d '\n'
Ugly as hell? Yes, but what's the alternative?Parsing text from a command is a headache, but it works most of the time. There often isn't an API or syscall to get the data you need on a specific system.
My favorite ugly hack is having a Ruby on Rails application write a file to disk so it can be processed by another program using a shell and then picking up the output file after that program finishes.
This requires a lot of cleanup and diligence to keep from leaking files... or you can set up a nightly cronjob using find to locate all of the files created more than a week ago and delete them. :)
Linux and Unix are a pile of hacks. It isn't going to change anytime soon.
If Dash was POSIX compliant, this wouldn't be necessary, but it isn't, so hacky text parsing is sadly necessary.
I'm immediately turned off by this person. They don't say exactly who or when the command was altered to put the warning in place, but it sounds like one inept, opinionated person decided to flip a switch without caring about any other practical reasons that conflict with his puritan take.
Seems fine to deprecate its usage inside bash scripts or scripts that you know are pegged to an interpreter that implements `command`, though.
Maybe it's there from when the default login shell was `tcsh`, since tcsh doesn't include a `command` builtin. In that case, it would provide the same functionality as long as no one defines a tcsh function or alias called `command`.
Removing it from the standard distribution would be a huge annoyance to everyone who uses it. One more package you have to remember to install on every system to be productive.
Everyone has different preferences though, e.g. for me vim is an essential package. That's why I have a few functions in my bashrc that installs packages in different environments. Here are some of them, with a representative excerpt of the packages:
- function defaultinstall { apt install curl sudo vim ping etc. }
- function defaultinstall_laptop { apt install lshw powertop gnome-power-manager etc. }
- function defaultinstall_wifi { apt install wavemon iw etc.
- function defaultinstall_android { apt install sqlite3 etc. }
- function defaultinstall_optional with various languages like php and ruby, a mariadb client, cloc, gifsicle, iperf3, apt-file and it then runs apt-file update, etc.
Before having these functions, I noticed that I'd often be missing packages (sometimes while offline). If you really want `which`, you can install the variant you want. I would do the same (because, interactively, I find `which` easier to type, even if I use the portable `command -v` in scripts).
Since `which` is an external command (it's built into some shells, but not bash), it doesn't know about aliases, shell functions, or builtin shell commands.
I've found that bash's built-in `type` command (with its various options) does whatever `which` does, and often does it better.
I also use `command -v foo >/dev/null` to detect whether the command `foo` exists -- for example:
if command -v less >/dev/null ; then
export PAGER=less
fi
I suppose I could also use `type` for the same purpose.It would be nice if `type` and/or `command` had an option to check whether a command exists without printing anything, but having to add `>/dev/null` is only a minor annoyance.
You can see more about "command" here: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/c...
- ‘command -v’, also will not display binary if its file permission is too restrictive.
- ‘whereis -b’ works just fine as long as /usr/sbin has world RX file mode or other lesser matching filemods.
Still stuck on ‘whereis’
Try this:
command -V command
command -V whichBetter to follow standards anyway.
Linux overall has an amazing separation of concerns structure (inherited from the POSIX tradition). The user-facing details you might be worried about like the interface design etc. are all handled by separate teams that expect their base to be reliable and stable so they can make other changes.
They why did they switch to systemd? It seems like linux developers have nothing better to do than just rename stuff with no obvious advantage to the new standards but breaking backwards compatibility with the old standards.
In my opinion, this is a good thing. Aiming for increasing "market share for average consumers" usually implies focusing on the standard baseline of functionality. There is nothing wrong with this, but this invariably cuts off tinkerers and enthusiasts who care about playing with SDRs and LIDARs and other fringe capabilities as much as (and usually more than) they care about the simplicity of the WiFi setup.
For simplest possible internet browsing there is ever-simpler Windows, with its design choices such as sharing of WiFi access and creeping ads. Just my 2c.
Seeing as mobile internet outstrips desktop internet, and Android is the majority of mobile internet devices, the Linux kernel runs under one of the top two pluralities of client side web browsing.
Since Debian does this all out in the open, we just get to watch how the sausage is made.
If you don't understand why something like this is important to get right, I'd suggest maybe finding out why other people do actually care about things like this.
Or maybe reflect on why Microsoft spends so much money and energy on backwards compatibility.
The Microsoft approach would be to support `which` forever. It's not a big enough quirk to justify removing it, and it's essential for some people's development process.
> 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.
No tempest, no bikeshedding. That seems like the polar opposite of whatever you are criticizing.
Makes it easier to avoid burning time on problems with equivalently-good solutions, or even not-equivalently-good-but-perfection-isn't-worth-the-cost-of-discovery.
Nevertheless, I think that if you can make it work then you get better decisions. Debian's been pretty good at it (systemd aside :-)