Due to work I have recently started using OS X and have set it up using homebrew in order to get a similar experience as with Linux.

However, there are quite a few differences in their settings. Some only need to be in place on one system. As my dotfiles live in a git repository, I was wondering what kind of switch I could set in place, so that some configs are only read for Linux system and other for OS X.

As to dotfiles, I am referring, among other, to .bash_profiles or .bash_alias.

  • I did this with git branches. I have one for FreeBSD, Gentoo and Ubuntu. But this is not ideal. – Raphael Ahrens Jul 17 '13 at 9:05
  • @RaphaelAhrens I want to avoid such a branch-based solution as it is prone to diverge. – k0pernikus Jul 17 '13 at 9:07
  • Yeah, you can make it a little bit easier when you put the system specific stuff into special files. But as i said not ideal. – Raphael Ahrens Jul 17 '13 at 9:09
  • stackoverflow.com/questions/394230/… You can check for Darwin on OS X. – Raphael Ahrens Jul 17 '13 at 9:19
  • My approach basically boils down to if (exists rcfile.local); source rcfile.local; endif, translated to the appropriate rc file. The main rc file I try to keep system agnostic, while the .local version has system specific settings. If you want it all in a single repo you can have system dirs and symlink the rcfile.local to the one in the correct directory. – jw013 Jul 17 '13 at 18:07

Keep the dotfiles as portable as possible and avoid OS dependent settings or switches that require a particular version of a tool, e.g. avoid GNU syntax if you don't use GNU software on all systems.

You'll probably run into situations where it's desirable to use system specific settings. In that case use a switch statement with the individual settings:

case $(uname) in
  'Linux')   LS_OPTIONS='--color=auto --group-directories-first' ;;
  'FreeBSD') LS_OPTIONS='-Gh -D "%F %H:%M"' ;;
  'Darwin')  LS_OPTIONS='-h' ;;

In case the configuration files of arbitrary applications require different options, you can check if the application provides compatibility switches or other mechanisms. For vim, for instance, you can check the version and patchlevel to support features older versions, or versions compiled with a different feature set, don't have. Example snippet from .vimrc:

if v:version >= 703
  if has("patch769")
    set matchpairs+=“:”
  • uname -s is like uname. uname stands for Unix name. – Stéphane Chazelas Jul 17 '13 at 9:59
  • 1
    @StephaneChazelas It just happens to be or is it guaranteed across systems and I can always drop the -s? – Marco Jul 17 '13 at 10:01
  • 1
    yes, uname alone has been the canonical way to do it for decades and is specified by POSIX. The original uname (in PWB Unix) didn't take any option. – Stéphane Chazelas Jul 17 '13 at 10:09
  • @StephaneChazelas Thanks for the clarification, I removed the -s from this answer and I'll keep it in mind for my future scripts. – Marco Jul 17 '13 at 10:11
  • It's a relatively minor detail and doesn't detract from the point illustrated by your example, but are those quotes in the vimrc set really supposed to be U+201C and U+201D rather than U+0022? – a CVn Jul 22 '13 at 11:16

If you are only concerned with files that are actually executed, such as .bash_profiles and friends, you may be able to get away with using e.g. uname to differentiate based on the system the code runs on.

For example, completely untested and with the caveat that I don't have an OS X to try things on, if you currently have on Linux:

alias ll='ls -lFA'

and on Mac OS X:

alias ll='ls -lFAx'

(where -x makes OS X's ls do something which GNU ls does by default), then they can be combined into something like this:

OS="$(uname -s)"
if test "$OS" = "Darwin"; then
    alias ll='ls -lFAx'
    # ...other OS X-specific things go here...
else if test "$OS" = "Linux"; then
    alias ll='ls -lFA'
    # ...other Linux-specific things go here...
# ...generic things go here...

The only requirement then is that uname -s works in mostly the same way (it should, since both systems are reasonably POSIX-y and uname -s is required by POSIX (thanks Marco for pointing this out)), and that the syntax for shell script branching based on a string comparison is the same. You can probably test based on other criteria as well; e.g., you could look for /etc/lsb_release, check whether /proc/sys/kernel/ostype contains "Linux", or whatever other tests you can come up with.

  • @RaphaelAhrens It's Darwin, I just checked. – k0pernikus Jul 17 '13 at 9:25
  • @RaphaelAhrens Like I wrote, I don't have an OS X to try things on, so I took a wild guess to show the idea rather than spending a lot of time on one relatively insignificant detail which the OP can trivially find out. – a CVn Jul 17 '13 at 9:28
  • Wikipedia to the rescue en.wikipedia.org/wiki/Uname if someone else wants there bash for Windows or other stuff. – Raphael Ahrens Jul 17 '13 at 9:30
  • 1
    The uname -o switch is not POSIX and fails on many systems, e.g. Solaris. -s is mandatory on POSIX and the most compatible way. IEEE Std 1003.1 – Marco Jul 17 '13 at 9:34
  • 2
    OSTYPE is not available in a POSIX shell. It will fail for example on a default FreeBSD installation and can only be used in .bashrc or .zshrc. It doesn't work reliably in .profile, .alias, etc. Since we're talking about compatibiliy here, I'd advice to go the safe way, instead of relying on particular shell's features, which are not guaranteed to be available on every system. – Marco Jul 17 '13 at 9:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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