Windows vs Linux Differences
Windows and Linux differ in small ways that cause real bugs when code or scripts move between them: path separators, case rules, line endings, permissions and tooling.
Quick comparison
| Area | Windows | Linux |
|---|---|---|
| Path separator | \ (many APIs also accept /) |
/ |
| Roots | Drive letters: C:\, D:\ |
One root: / |
| Case in file names | Insensitive, preserves case | Sensitive |
| Line endings | CRLF (\r\n) |
LF (\n) |
Path list separator (PATH) |
; |
: |
| Permissions | ACLs, elevation (UAC) | Owner/group/other bits, sudo |
| Executables | Extension decides (.exe, .ps1) |
The execute bit decides |
| Packages | winget, MSI installers |
apt, dnf, … |
| Default shell | PowerShell, Command Prompt | Bash (or similar) |
| Environment variable syntax | $env:NAME, %NAME% |
$NAME |
What goes wrong in practice
- Case sensitivity:
import './Utils'works on Windows when the file isutils.js, and fails on Linux. Match the case of file names exactly, everywhere. - Hard-coded paths:
"data\\config.json"orC:\tempbreaks elsewhere. Use your language’s path-joining function and a temp-directory API instead of string concatenation. - Line endings: a shell script with CRLF fails on Linux with errors such as
bad interpreter: /bin/bash^M. Let Git manage it: setcore.autocrlfas your team prefers or use a.gitattributesfile (for example*.sh text eol=lf). See Git Fundamentals. - Missing execute bit: a script committed from Windows may not be executable on Linux.
git update-index --chmod=+x script.shfixes it in the repository. - Reserved names and characters: files named
aux,conor containing:cannot be created on Windows, even though Linux allows them. - Different commands:
dir,typeandcopyare Command Prompt,Get-ChildItemis PowerShell,ls,catandcpare Bash. See Command Line Basics.
Try it
In a Linux shell, create Test.txt and test.txt in one folder and list them. Try the same on Windows. Then find a script of yours, check its line endings with file script.sh, and see what a CRLF file does when you run it in WSL.
Common mistakes
- Importing a file with the wrong case, which works on Windows and fails on Linux.
- Hard-coding paths such as `C:\temp` instead of using path-joining and temp-directory functions.
- Committing a shell script with CRLF endings, which fails on Linux with a `bad interpreter` error.
- Forgetting the execute bit on a script committed from Windows.
Check yourself
- Why can `import './Utils'` work on Windows and fail on Linux?
- What does `bad interpreter: /bin/bash^M` mean, and how do you prevent it?
- Which separator does the `PATH` variable use on each system?