6

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

#!/bin/bash
if [ no idea ]; then
    #installed, nothing to do...
else
    xcode-select --install
fi

Thanks for any suggestions.

0

3 Answers 3

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

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.

8
  • That's perfect. So I was missing that -x. Thank you Daniel. I see that replacing -print-path with just -p works as well. Commented Dec 14, 2015 at 9:15
  • Depending on the quality of the checking you want to achieve, a type xcode-select and a -d could be necessary.
    – dan
    Commented Dec 14, 2015 at 9:23
  • I'd use: if [ -d "$(xcode-select -p)" ]; then Commented Dec 14, 2015 at 14:09
  • 1
    With the help of remarks of @user3439894, I put here or more general shell check of Xcode correct install.
    – dan
    Commented Dec 14, 2015 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) Commented Dec 14, 2015 at 15:11
5

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

$ xcode-select -p
/Applications/Xcode.app/Contents/Developer
$ if type xcode-select >&- && xpath=$( xcode-select --print-path ) &&
    test -d "${xpath}" && test -x "${xpath}" ; then echo "installed" ; fi
installed
$ 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;
else
  echo not installed, installing;
fi

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

3
  • 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?
    – dan
    Commented Dec 14, 2015 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. Commented Jan 8, 2017 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 Commented Jan 11, 2017 at 5:24
1

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"
        count=0
        pkgutil --files com.apple.pkg.CLTools_Executables |
        while IFS= read file
        do
        test -e  "/${file}"         &&
        printf '%s\n' "/${file}…OK" ||
        { printf '%s\n' "/${file}…MISSING"; ((count++)); }
        done
        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"
        fi
else   printf '%s\n' "Command Line Tools are not installed"
       # Provide instructions to install the Command Line Tools
fi
2
  • 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. Commented Jan 11, 2017 at 6:15
  • The command line tools are not always installed with the com.apple.pkg.CLTools_Executables package. They may instead be part of Xcode… Commented Jan 17, 2022 at 13:54

You must log in to answer this question.

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