Using bash, I want to check if Command Line Tools are installed.

Currently they are and when I type xcode-select --install I get:

xcode-select: error: command line tools are already installed, use "Software Update" to install updates It appears Homebrew is already installed. If your intent is to reinstall you should do... blah blah blah

Basically my problem is that I have several methods to check in bash (using if / fi) but I don't know which solution is the best one.

1) I can do xcode-select -p and that returns the path /Library/Developer/CommandLineTools but then how I should build the if statement? I don't know what will be presented when CLT are not installed.

2) I can do xcode-select --version. Should I then grep for a phrase version since I get

xcode-select version 2343.

3) I can do which xcode-select but again, in all cases I'm not sure how the if should look like. I also think that grep is not the best way, since in the future the output may be different in future version of OSX.

To sum up I would like something like

if [ no idea ]; then
    #installed, nothing to do...
    xcode-select --install

Thanks for any suggestions.

if type xcode-select >&- && xpath=$( xcode-select --print-path ) &&
   test -d "${xpath}" && test -x "${xpath}" ; then
   #... is correctly installed
   #... isn't correctly installed

Strangely, the --print-path isn't documented in old Xcode versions but is working as -print-path. On the other hand, the -p option doesn't have this compatibility.

  • That's perfect. So I was missing that -x. Thank you Daniel. I see that replacing -print-path with just -p works as well. – Matt Komarnicki Dec 14 '15 at 9:15
  • Depending on the quality of the checking you want to achieve, a type xcode-select and a -d could be necessary. – daniel Azuelos Dec 14 '15 at 9:23
  • I'd use: if [ -d "$(xcode-select -p)" ]; then – user3439894 Dec 14 '15 at 14:09
  • 1
    With the help of remarks of @user3439894, I put here or more general shell check of Xcode correct install. – daniel Azuelos Dec 14 '15 at 15:02
  • 1
    Shouldn't ${xpath} be double quoted to prevent globbing and word splitting? Also, why are you placing spaces around xcode-select --print-path in $( xcode-select --print-path )? There doesn't need to be and should simply be: $(xcode-select --print-path) – user3439894 Dec 14 '15 at 15:11

Just because code-select returns a valid path doesn't mean the command line tools are installed:

$ xcode-select -p
$ if type xcode-select >&- && xpath=$( xcode-select --print-path ) &&
    test -d "${xpath}" && test -x "${xpath}" ; then echo "installed" ; fi
$ xcode-select --install
xcode-select: note: install requested for command line developer tools

Thus, a more accurate check is to use xcode-select to try and install the CLT with the following:

if xcode-select --install 2>&1 | grep installed; then
  echo installed;
  echo not installed, installing;

If it's not installed, it will prompt for installation as your example shows, but without a separate line for the xcode-select --install.

  • Is the first code you run the consequence of a 1st xcode-select --install followed by a move of the registered Xcode path with xcode-select --switch /tmp? – daniel Azuelos Dec 14 '15 at 18:44
  • In macOS Sierra 10.12.2, if CLT is already installed xcode-select --install 2>&1 results in stderr: xcode-select: error: command line tools are already installed, use "Software Update" to install updates, but you wouldn't want to suppress that either for the case when it isn't installed. I'm stumped. – Lloyd Dewolf Jan 8 '17 at 23:18
  • @fd0 looks to be the way to go. On a clean Sierra MacOS 10.12.1: ENTER: $ pkgutil --pkg-info=com.apple.pkg.CLTools_Executables RESULT: No receipt for 'com.apple.pkg.CLTools_Executables' found at '/'. ENTER: $ echo $? RESULT: 1 – Lloyd Dewolf Jan 11 '17 at 5:24

Yet another approach would be to use pkgutil

if      pkgutil --pkg-info com.apple.pkg.CLTools_Executables >/dev/null 2>&1
then    printf '%s\n' "CHECKING INSTALLATION"
        pkgutil --files com.apple.pkg.CLTools_Executables |
        while IFS= read file
        test -e  "/${file}"         &&
        printf '%s\n' "/${file}…OK" ||
        { printf '%s\n' "/${file}…MISSING"; ((count++)); }
        if      (( count > 0 ))
        then    printf '%s\n' "Command Line Tools are not installed properly"
                # Provide instructions to remove and the CommandLineTools directory
                # and the package receipt then install instructions
        else    printf '%s\n' "Command Line Tools are installed"
else   printf '%s\n' "Command Line Tools are not installed"
       # Provide instructions to install the Command Line Tools
  • I looked in the source code of homebrew and Homebrew/os/mac/xcode.rb looks to use this type of approach. Looking at homebrew was interesting to me as I could see the evolution of the CLT integration in MacOS. – Lloyd Dewolf Jan 11 '17 at 6:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .