Handling Cross-Platform sed Compatibility in Shell Scripts

When writing shell scripts that need to run across different operating systems, it’s important to consider platform-specific differences…

Handling Cross-Platform sed Compatibility in Shell Scripts
Photo by Alvan Nee on Unsplash

When writing shell scripts that need to run across different operating systems, it’s important to consider platform-specific differences. One such difference is how the sed (stream editor) command handles in-place editing.

The Issue with sed -i

The -i option in sed is used for in-place editing, meaning it modifies files directly instead of printing changes to standard output. However, its syntax differs between macOS and Linux (or Git Bash on Windows):

  • Linux/Git Bash (Windows): sed -i 's/old/new/g' file
  • macOS (BSD sed): sed -i '' 's/old/new/g' file

On macOS, sed -i requires an additional argument specifying the extension for backup files. If no backup is needed, an empty string ('') must be provided. On Linux, sed -i works without an extra argument.

Writing a Cross-Platform Compatible Script

To ensure your script runs on both macOS and Linux/Git Bash, you can use a conditional check based on $OSTYPE:

if [[ "$OSTYPE" == "darwin"* ]]; then 
    # macOS 
    SED_CMD="sed -i ''" 
else 
    # Linux/Git Bash (Windows) 
    SED_CMD="sed -i" 
fi

With this setup, you can use $SED_CMD in your script for in-place modifications:

$SED_CMD 's/old/new/g' file.txt

Explanation of the Code

  • The script checks the $OSTYPE variable, which contains the operating system type.
  • If $OSTYPE starts with darwin, it means the script is running on macOS, so sed -i '' is used.
  • Otherwise, it assumes Linux or Git Bash on Windows and uses sed -i without an empty string.

Example Use Case

If you need to replace a word in a file across platforms, you can write a script like this:

#!/bin/bash 
 
if [[ "$OSTYPE" == "darwin"* ]]; then 
    SED_CMD="sed -i ''" 
else 
    SED_CMD="sed -i" 
fi 
 
# Replace 'foo' with 'bar' in sample.txt 
$SED_CMD 's/foo/bar/g' sample.txt

Alternative Approach Using gsed

For users who frequently work across platforms, installing GNU sed on macOS can simplify scripts. You can install it via Homebrew:

brew install gnu-sed

Then use gsed instead of sed to ensure compatibility with Linux sed behavior:

gsed -i 's/old/new/g' file.txt

Conclusion

When writing shell scripts for cross-platform compatibility, always test commands like sed on different systems. Using an OS check with $OSTYPE or installing GNU tools can help maintain consistency and prevent unexpected errors.