How to handle with problems with different commands on FreeBSD/Linux/macOS

Introduction

Due to the different commands between Linux (GNU coreutils) and FreeBSD, macOS, it is necessary to consider the environment in which the script is executed in the shell script. For example, if you want to get the last modified date and time of a file, you want stat to use it, but stat the flags that specify the output format are different between GNU coreutils, FreeBSD, and macOS.

I think it’s true that you can write in Perl or Python as a premise, but there are some things that you can’t do without shell scripts such as bash and zsh plugins. It’s a trivial matter if you just write it yourself and use it yourself, but it’s not so if it’s shared with others.

TL; DR

  • Take advantage of syntax differences (stat)
  • Substitute with a command with the same syntax (openssl)

Determine the environment by uname

There is a judgment by the most common coping method .

case "$(uname)"; in
Linux)
# GNU coreutils
;;
Darwin)
# macOS
;;
esac

This has one big problem: if you’re using GNU coreutils on macOS, the environment-based decision will fail in the first place. I’m using the shell script I use because I want to assume GNU coreutils. From the above, it is not so good to judge by the environment.

Take advantage of the difference in syntax

For example stat, the — help flag only exists in GNU coreutils, so it can be determined by the exit code when it is executed.

if stat --help >/dev/null 2>&1; then
modified_time_fmt="-c%y" # GNU coreutils
else
modified_time_fmt="-f%m" # FreeBSD, macOS
fi
stat $modified_date_fmt /path/to/file # It works!

This doesn’t depend on the environment, so it works well if you’re using GNU coreutils on macOS, but it’s best if you can use it without making a decision in the first place.

Substitute with a command that has the same syntax

I want to get md5. You md5sum can use it with GNU coreutils, but you md5 need to use this command on macOS and FreeBSD because it doesn’t exist .

You openssl can choose to use it in this case . openssl Is an OpenSSL command line utility, so there are differences depending on the version, but not on the environment.

$ openssl md5 test
MD5(test)= d41d8cd98f00b204e9800998ecf8427e

Since this method openssl assumes that is installed, the conditions that can be used are different from other methods, but it can be considered as an option.

Conclusion

Since shell scripts have problems due to differences in execution environment, it is better to keep them small even when using them.

 by the author.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store