Different versions of shell commands like PHP, Vi – find the true location of Mac/Unix commands, aliases and links

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.

Debugging Aliases

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'

Debugging Links

Links act slightly different again. As discovered in this blog post, vi links to vim on a mac, however the which, 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.

Please share if you find our free website useful, it really helps us produce more tutorials!

Advertisements

Leave a Reply