Sometimes it can be a challenge to uncover what terminal command is actually being run on Mac / Unix / Linux systems. Over time, old aliases, links and the repeated installation, upgrading and removal of software can lead to existing and even untouched default commands either unable to be found or running a different version than expected.
Recently we have been using Homebrew to swap in and out multiple versions of PHP (5.4, 5.6, 7.1 etc.) on Macs. Whilst great for quickly testing and developing across versions, this makes it possible to have strange occurrences, like the
$ which [command] returning a different version of the software to the one which the shell actually executes!
The following location mismatch demonstrates the problem:
# Problem: Command or Software (in this case php) # Reported as missing or runs at different location $ php -v -bash: /usr/local/bin/php: No such file or directory $ which php /usr/bin/php # WTF ???
Different locations are being referenced by
$ which [command] and the shell.
To fix the discrepancy, use the
$ hash [command] to refresh the shell’s command location cache:
# Result before hash command $ command -v php /usr/local/bin/php $ hash php $ # Result after command $ command -v php /usr/bin/php # Same version recognized everywhere $ which php /usr/bin/php $ php -v PHP 5.5.36 (cli) (built: May 29 2016 01:07:06) Copyright (c) 1997-2015 The PHP Group Zend Engine v2.5.0, Copyright (c) 1998-2015 Zend Technologies
Great, order has returned to the universe and which is again pointing at the correct place. Keep in mind if you do replace (or re-link) the php at /usr/local/bin/php it will be executed instead of the /usr/bin/php, but now all commands should agree on the file’s location.
The above situation can be particularly tricky when dealing with aliases.
If we define an alias and confirm it can be executed, the
$ which [alias] and
ls commands bizarrely return nothing! Where is the alias going? To find where and what the alias is actually running, utilise the
$ type -a [command] command:
# Create alias and watch the confusing behavior $ alias phpv='php -v' phpv PHP 5.5.36 (cli) (built: May 29 2016 01:07:06) Copyright (c) 1997-2015 The PHP Group Zend Engine v2.5.0, Copyright (c) 1998-2015 Zend Technologies $ which phpv $ $ ls -l phpv ls: phpv: No such file or directory # The type command reveals all (-a) $ type -a phpv phpv is aliased to `php -v'
Links act slightly different again. As discovered in this blog post, vi links to vim on a mac, however the
type -a and
command -v commands only shows the link name, not the target:
# These commands give information on links (ls -l is most useful) $ which vi /usr/bin/vi $ type -a vi vi is /usr/bin/vi $ command -v vi /usr/bin/vi $ ls -l /usr/bin/vi lrwxr-xr-x 1 root wheel 3 21 Aug 15:29 /usr/bin/vi -> vim
Here we can see that although
ls -l was useless for aliases and commands, it is good for showing where links point to.
Although only a summary, these quick commands give a few pointers for when a command either cannot be found or a different version than expected is executing. If you’re still struggling to locate an executed command or know of other handy tips, please leave a comment.