Cross-Platform Stata Do-Files

Write Stata do-files that run on both Windows and Linux without modification — path handling, OS detection macros, and CI-friendly patterns.

Intermediate Verified Working Updated 6 min read Tested on Zorin OS 18.1 Pro (Ubuntu 24.04 Noble base) + Windows 10/11 Hardware Lenovo ThinkPad L14 Gen 2

What This Guide Achieves

GoalStatus
Make existing do-files run on Windows, Linux, and macOS without changesDone
Verify that Stata produces identical output on both OSDone
Handle path differences between operating systems automaticallyDone

The Problem (Windows User Perspective)

When you use Stata on Windows, your do-files have hardcoded paths like:

cd "C:\Users\mohsin\Dropbox\Research\ProjectName"
global data "C:\Users\mohsin\Dropbox\Research\ProjectName\data"

These paths break instantly on Linux (which uses /home/mohsin/Dropbox/...) or macOS (which uses /Users/mohsin/Dropbox/...). If you work across multiple machines or collaborate with others on different operating systems, you need a way to detect the OS and set paths automatically.


Solution: OS Detection Pattern

Add this block at the top of every do-file, before any path-dependent code:

* ============================================================
* CROSS-PLATFORM PATH CONFIGURATION
* ============================================================
* Detect operating system
if "`c(os)'" == "Windows" {
    local is_windows = 1
    local is_linux   = 0
    local is_mac     = 0
}
else if "`c(os)'" == "Unix" {
    local is_windows = 0
    local is_linux   = 1
    local is_mac     = 0
}
else if "`c(os)'" == "MacOSX" {
    local is_windows = 0
    local is_linux   = 0
    local is_mac     = 1
}

* Set root path based on OS and username
local username = "`c(username)'"

if `is_windows' {
    if "`username'" == "mohsin" {
        global root "C:/Users/mohsin/Dropbox/Research/ProjectName"
    }
    else {
        di as error "Unknown Windows user: `username'"
        exit 198
    }
}
else if `is_linux' {
    if "`username'" == "mohsin" {
        global root "/home/mohsin/Dropbox/Research/ProjectName"
    }
    else {
        di as error "Unknown Linux user: `username'"
        exit 198
    }
}
else if `is_mac' {
    if "`username'" == "mohsin" {
        global root "/Users/mohsin/Dropbox/Research/ProjectName"
    }
    else {
        di as error "Unknown macOS user: `username'"
        exit 198
    }
}

* Fail-safe: exit if root is not set
if "$root" == "" {
    di as error "ERROR: root path not set. Check OS/username configuration."
    exit 198
}

* Set sub-path globals (all absolute, based on root)
global data     "$root/data"
global output   "$root/output"
global tables   "$root/tables"
global figures  "$root/figures"
global dofiles  "$root/do-files"
global logs     "$root/logs"

* Change to project root
cd "$root"

Key Points

  • c(os) returns "Windows", "Unix" (for Linux), or "MacOSX"
  • c(username) returns the current system username
  • Use forward slashes (/) in all paths — Stata handles them on every OS, including Windows
  • exit 198 is Stata’s standard error code for “something is wrong” — stops execution immediately
  • All sub-path globals are absolute — no relative paths that break when cd changes

Adding a New Collaborator

When a collaborator on a different machine needs to run your do-file, they add one line inside the appropriate OS block:

else if "`username'" == "sarah" {
    global root "C:/Users/sarah/Documents/SharedProject"
}

No other changes needed — all sub-path globals derive from $root.


Verifying Output Across Operating Systems

After running the same do-file on both Windows and Linux, verify the output matches:

What to Compare

CheckHowExpected Result
Seed valuedisplay c(seed)Identical hex string on both OS
Sort seeddisplay c(sortseed)Identical on both OS
RNG statedisplay c(rngstate)Identical if same operations run
Regression coefficientsRun the same regressionIdentical to all decimal places
Standard errorsCompare SE columnsIdentical
Sample size (N)Check observation countsIdentical
Variable typesdescribeIdentical

What May Differ (and That’s OK)

DifferenceWhy It’s Normal
File paths in log outputDifferent OS = different paths
TimestampsDifferent time zones / run times
Stata version display lineMay show different OS in header
Floating-point formattingLast digit may differ (cosmetic, not statistical)

Verified Result

Stata 19 MP produces byte-identical statistical output on Windows and Linux when:

  • Same Stata version and edition (MP, SE, BE)
  • Same dataset
  • Same seed set before randomization
  • Same do-file logic

The seed values, sort seeds, coefficients, standard errors, and sample sizes matched exactly across Windows and Linux in our testing.


Path Conventions Reference

ComponentWindowsLinuxmacOS
Home directoryC:\Users\username/home/username/Users/username
Path separator\ (backslash)/ (forward slash)/ (forward slash)
Stata install pathC:\Program Files\Stata19/usr/local/stata19/Applications/Stata
Stata binaryStataMP-64.exestata-mpStataMP
Do-file extension.do.do.do
In Stata codeUse / (works on all OS)Use /Use /

Template Do-File

A minimal cross-platform template you can copy into new projects:

* ============================================================
* Project: [Project Name]
* Author:  [Md Mohsin Hossain]
* Date:    [15-04-2026]
* Stata:   19 MP
* ============================================================

clear all
set more off
capture log close

* --- OS Detection ---
if "`c(os)'" == "Windows" {
    local is_windows = 1
}
else {
    local is_windows = 0
}

if "`c(os)'" == "Unix" {
    local is_linux = 1
}
else {
    local is_linux = 0
}

if "`c(os)'" == "MacOSX" {
    local is_mac = 1
}
else {
    local is_mac = 0
}

* --- User/Path Dispatch ---
local username "`c(username)'"

if `is_windows' & "`username'" == "mohsin" {
    global root "C:/Users/mohsin/Dropbox/Research/ProjectName"
}
else if `is_linux' & "`username'" == "mohsin" {
    global root "/home/mohsin/Dropbox/Research/ProjectName"
}
else if `is_mac' & "`username'" == "mohsin" {
    global root "/Users/mohsin/Dropbox/Research/ProjectName"
}
else {
    di as error "Unknown OS/user combination: `c(os)' / `username'"
    exit 198
}

* --- Sub-Paths ---
global data    "$root/data"
global output  "$root/output"
global tables  "$root/tables"
global figures "$root/figures"

cd "$root"
log using "$output/analysis_log", replace

* ============================================================
* ANALYSIS CODE BELOW (no hardcoded paths)
* ============================================================

use "$data/mydata.dta", clear

* [your analysis here]

log close

What Didn’t Work (and Why)

Approach TriedWhy It Failed
Using backslashes (\) in pathsOnly works on Windows — breaks on Linux/macOS
Using relative paths (cd "../data")Breaks when working directory changes or when running from different locations
Hardcoding a single user’s pathBreaks for collaborators or when switching between machines
Using environment variables ($HOME)Stata doesn’t expand shell environment variables — use c(username) instead
Skipping the exit 198 fail-safeDo-file silently uses wrong paths if OS/user isn’t recognized

Discussion