Skip to content

Instantly share code, notes, and snippets.

@maelvls
Last active February 15, 2023 12:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maelvls/0e216cd7da88800a70b9ec8429508fd0 to your computer and use it in GitHub Desktop.
Save maelvls/0e216cd7da88800a70b9ec8429508fd0 to your computer and use it in GitHub Desktop.

The slight differences between Unix tools across BSD (incl. macOS), GNU/Linux, and Busybox

This is a list of discrepencies I came across while trying to while cross-system compatible makefiles and Bash scripts.

sed

-i (in-place editing) can work without an argument with GNU sed, but won't work without an argument on BSD sed and on Busybox.

On BSD sed and Busybox sed, you have to give an argument that corresponds to the suffix added to the file name when the back up file is created. The following works on BSD, GNU, and Busybox sed:

sed -i.bak 's|foo|bar|' file
rm -f file.bak

Alternatively, you can use perl:

perl -pie 's/foo/bar/g'

-E doesn't work with BSD sed but works on Busybox and GNU sed. Because of this, |, +, \s, ?, and \t don't work, as explained in the article BSD sed vs. GNU sed. For example,

echo somefoootherbartext | sed -E "s/(foo|bar)//g"

produces:

# GNU sed
someothertext

# BSD sed
somefoootherbartext

# Busybox sed
someothertext

Instead you can use:

sed -e "s/foo//g" -e "s/bar//g"

awk

-i (in-place editing) only works 1 with recent versions of GNU awk (4.1.0 and above). On BSD, the only solution is to use a temporary file:

awk '{print $0}' file > tmp && mv tmp file

xargs

-I'{}': BSD xargs only replaces the 5 first arguments. For example,

echo OK | xargs -I'{}' echo arg1-'{}' arg2-'{}' arg3-'{}' arg4-'{}' arg5-'{}' arg6-'{}'

produces:

# GNU xargs
arg1-OK arg2-OK arg3-OK arg4-OK arg5-OK arg6-OK

# BSD xargs
arg1-OK arg2-OK arg3-OK arg4-OK arg5-OK arg6

# Busybox xargs
arg1-OK arg2-OK arg3-OK arg4-OK arg5-OK arg6-OK

The flag --max-procs is only available on GNU xargs and BSD xargs but not on Busybox xargs. Instead, you can use -P.

date

-v (adjust value) only works on BSD date. The equivalent on GNU date is -d but with a slightly different way of giving the duration. On busybox, this flag doesn't exist.

BSD GNU Busybox
date -v+12H date -d+12hours not available
Thu Oct 13 20:43:03 CEST 2022 Thu Oct 13 08:44:52 PM CEST 2022 n/a

find

On macOS, -d means "max depth" and takes a parameter. On GNU find, -d means "depth first" and takes no parameter. On GNU find, you will get the following error message if mistakenly you use -depth 1 or -d 1:

$ find . -depth 1
find: paths must precede expression: `1'

To sum up, the "max depth" can be achieved with the following:

# GNU find
find . -maxdepth 1

# macOS
find . -depth 1
find . -d 1

On macOS, -printf "%P\n" won't work. On GNU find, %P displays the relative path instead of the absolute path whe find is being run with a different folder than the current folder.

$ find . -d 1 -type f -printf "%P\n"
find: -printf: unknown primary or operator

No know workaround.

Dash vs. Bourne shell (sh)

Footnotes

  1. https://stackoverflow.com/questions/16529716/save-modifications-in-place-with-awk

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment