6

This question already has an answer here:

On my main machine, a MacBook Pro, I have a .bash_profile file that I'd like to use unaltered on my Dreamhost linux machine. However, there's a few lines that are only applicable to macOS, such as alias mvim="/Applications/MacVim.app/Contents/MacOS/MacVim".

Is there a way in bash to test for whether it's running under macOS or Debian (or just not macOS) and only execute that above line, and a few others, when running under macOS? Whereas other questions here address how to find out which Linux distro is being used, here I only need to know if I'm running on macOS or Linux, and the solutions for knowing the Linux distro aren't available on macOS.

marked as duplicate by Raphael Ahrens, Anthon, terdon bash Jul 5 '16 at 10:45

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • What does uname -s show on a Mac? Under Linux, it returns Linux. – John1024 Jul 5 '16 at 0:03
  • Darwin, so, that helps quite a bit, along with Julie's suggestion. ty – Chuck Jul 5 '16 at 0:16
  • @cat not in this case. The question there and the answers seem to revolve around which Linux distro is being used, whereas I needed to know only whether I'm working on Linux or macOS (Darwin). uname seems to be perfect for that. – Chuck Jul 5 '16 at 5:04
  • @Chuck Oops, that question isn't the one I was looking for as a dupe. I swore we had a canonical "what's uname" etc question but I guess not – cat Jul 5 '16 at 5:10
10
if [[ $(uname -s) == Linux ]]
then
    doThis
else
    doThat
fi
  • Just in case someone doesn't see my comment above, using if [[ $(uname -s) == Darwin ]] in the first line will execute the then clause. – Chuck Jul 5 '16 at 0:23
  • @Chuck: Not sure what you mean. I tried to remove the then and it didn't work. – Julie Pelletier Jul 5 '16 at 0:30
  • I wasn't clear. I didn't mean to imply that then wasn't required, only that using Darwin works if you want then then clause to execute on macOS. – Chuck Jul 5 '16 at 1:00
  • 1
    Huh, and what happens if someone has the bright idea to make uname -s output blah"blah" or ]]; then :; fi; rm -rf / # ? – cat Jul 5 '16 at 5:13
  • 3
    @cat: uname is a built-in Unix command. If someone is stupid enough to do that, they should expect lots of problems. – Julie Pelletier Jul 5 '16 at 5:16
11

On OSX, uname -s returns Darwin (most Linux uname programs return Linux).

As a general rule (aside from personal use), uname has quirks for different systems. In autoconf, scripts use config.guess, which provides consistent information.

For example in my Debian 7,

x86_64-pc-linux-gnu

and in OSX El Capitan

x86_64-apple-darwin15.5.0

You could use if-then-else statements in the shell, or a case-statement. The latter are more easily maintained, e.g.,

case $(config.guess) in
*linux*)
    DoSomeLinuxStuff
    ;;
*apple-darwin*)
    DoSomeMacStuff
    ;;
esac

Many Linux distributions add information to the output of uname, but this is useful only on a case-by-case basis. There is no standard for the information added.

For my Debian 7:

$ uname -v
#1 SMP Debian 3.2.81-1

while OSX is radically different:

$ uname -v
Darwin Kernel Version 15.5.0: Tue Apr 19 18:36:36 PDT 2016; root:xnu-3248.50.21~8/RELEASE_X86_64

Further reading:

  • Thanks for the details, but while it sounds like config.guess is more robust than uname, for macOS, uname returns Darwin, and Linux won't return that no matter what, so that's sufficient for my needs. I suppose it's possible that a raw Darwin (no macOS GUI) will also return Darwin, I've never used such a system, only macOS, Linux, and (if I can't avoid it) Windows. – Chuck Jul 5 '16 at 5:33
1

As an alternate solution, you might try splitting your .bash_profile into a portable part and a system-specific part.

In your main .bash_profile add the following:

if [ -f ~/.bash_profile_local ] ; then
    . ~/.bash_profile_local
fi

Then put any customizations that apply only to a given system into .bash_profile_local on that system. If you have no customizations, you don't have to create the file.

Or, if you wanted to go even further and have pieces shared among some systems but not others, you could do a full-on SYSV-style rc.d directory. In .bash_profile:

if [ -d ~/.bash_profile.d ] ; then
    for f in ~/.bash_profile.d/* ; do
        if [ -f "$f" ] ; then
            . "$f"
        fi
    done
fi

Then create a .bash_profile.d directory, and any files you put in there will be run as if they were part of your .bash_profile.

  • Thanks, @Jander, but I do like the simplicity of the accepted solution. The platform-specific lines are very few (4 or so), and are mostly just alias declarations like the example I gave (MacVim, Sage, etc.), although I'll probably change the MacVim alias into a function so I can stop having to type mvim file & and just type mvim file. – Chuck Jul 5 '16 at 4:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.