> The which program has been deprecated, and writes a warning to standard error (but still works, so long as stderr is not being captured along with stdout). Shell script writers are advised to use command -v instead. Interactive bash shell users are advised to use type, or type -a. In zsh which is already a shell builtin, so interactive zsh users are not affected.
For most purposes, the difference is pretty nuanced and unlikely to cause a problem in real life.
> 'command -v' also returns 0 for shell built-ins, whereas 'which' only searches $PATH.
In what cases is one using anything to check for a built-in shell command? I've written quite a lot of bash, and this has never come up.
I've learned to prefer 'command -v' because it's always available, whereas on minimal or busybox installs sometimes 'which' is not included.
The annoying part seems to be more that the ergonomics of a single straightforwardly-named command (e.g. 'which') are friendlier and easier to remember compared to an unintuitively-named command requiring the addition of a flag.
Why can't we move in a more ergonomic direction by promoting 'which' to a BASH built-in?
Oh, according to LWN, it's Clint Adams' fault. In which case it's my fault, because in 1998, when Clint and I shared an apartment in NJ, I was pushing him backwards in a shopping cart, which overturned. He hit his head. All his decisions thereafter, I submit, are due to that.
> "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 one of the most ridiculous takes I've heard and severely out of touch with shell scripts out in the wild, to say nothing of the expectations of Unix users typing at an interactive shell.
First time I used Debian was '99 or 2000. It's been a go-to Linux distro for me for a long time. This is disappointing.
I stopped using which some time ago because while it worked fine to bootstrap Debian based distros I found out it wasn't included in arch. Since then I always default to command -v. I don't see the problem, it already wasn't portable and as can be seen in this thread including it gives the false impression that it was.
My house has machines running FreeBSD, OpenBSD, Linux, Mac, and lastly some old '90s Unix I never power on. Those all have which.
The only portability wrinkle I've personally seen is that old Solaris behaved differently when the program isn't found. It would say "no $1 in $PATH" to stdout, whereas more recent systems just don't display anything.
Kind of a moot point for me since I usually install fish the first chance I get anyway, which has for its command command:
> -v (or -s or --search)
'command --search' is much more accurate. To me, -v means either "version" or "verbose", and it's a stretch to say either of those words is suitable for this use case. Guess I'll have to remember it as vhich if the need arises :)
> To me, -v means either "version" or "verbose", and it's a stretch to say either of those words is suitable for this use case.
Well it is, kind of. From bash-builtins(7):
> If either the -V or -v option is supplied, a description of command is printed. The -v option causes a single word indicating the command or filename used to invoke command to be displayed; the -V option produces a more verbose description.
I was taught, back in the late 20th century, to never use the “which” program in shell scripts, since that program has its own logic on what programs are available, and that might differ from the method the actual shell uses to find programs, and this could obviously lead to subtle bugs. I was taught to use “type” instead, since, IIRC, “command” did not exist at the time.
> I was taught, back in the late 20th century, to never use the “which” program in shell scripts, since that program has its own logic on what programs are available, and that might differ from the method the actual shell uses to find programs, and this could obviously lead to subtle bugs.
This reminds me of the suggestion not to use access(2) and X_OK to decide to call execve(2) -- because the kernel behavior of executing the binary may work differently and fail for some other reason, or perhaps even there's a race condition where the executable bit gets removed between your calls.
This is typical advice given to people writing shells.
On this basis I would say using either which or command -v in unsound; neither of them are a guarantee that execve(2) will succeed. But like many things done in shell scripts, it's a "good enough" kind of solution that will do the right thing a majority of the time.
There are 4 freezes[1]... the soft freeze (the current one) basically freezes which packages will be in the release and the hard freeze (the next one) gets everything stabilized.
> The which program has been deprecated, and writes a warning to standard error (but still works, so long as stderr is not being captured along with stdout). Shell script writers are advised to use command -v instead. Interactive bash shell users are advised to use type, or type -a. In zsh which is already a shell builtin, so interactive zsh users are not affected.