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.
What This Guide Achieves
| Goal | Status |
|---|---|
| Make existing do-files run on Windows, Linux, and macOS without changes | Done |
| Verify that Stata produces identical output on both OS | Done |
| Handle path differences between operating systems automatically | Done |
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 198is Stata’s standard error code for “something is wrong” — stops execution immediately- All sub-path globals are absolute — no relative paths that break when
cdchanges
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
| Check | How | Expected Result |
|---|---|---|
| Seed value | display c(seed) | Identical hex string on both OS |
| Sort seed | display c(sortseed) | Identical on both OS |
| RNG state | display c(rngstate) | Identical if same operations run |
| Regression coefficients | Run the same regression | Identical to all decimal places |
| Standard errors | Compare SE columns | Identical |
| Sample size (N) | Check observation counts | Identical |
| Variable types | describe | Identical |
What May Differ (and That’s OK)
| Difference | Why It’s Normal |
|---|---|
| File paths in log output | Different OS = different paths |
| Timestamps | Different time zones / run times |
| Stata version display line | May show different OS in header |
| Floating-point formatting | Last 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
| Component | Windows | Linux | macOS |
|---|---|---|---|
| Home directory | C:\Users\username | /home/username | /Users/username |
| Path separator | \ (backslash) | / (forward slash) | / (forward slash) |
| Stata install path | C:\Program Files\Stata19 | /usr/local/stata19 | /Applications/Stata |
| Stata binary | StataMP-64.exe | stata-mp | StataMP |
| Do-file extension | .do | .do | .do |
| In Stata code | Use / (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 Tried | Why It Failed |
|---|---|
Using backslashes (\) in paths | Only 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 path | Breaks 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-safe | Do-file silently uses wrong paths if OS/user isn’t recognized |
Related Guides
- Stata 19 Complete Guide — Full installation and VS Code integration
- VS Code Setup — Editor configuration for Stata development
Discussion